Files
renderdoc/qrenderdoc/Code/Interface/CommonPipelineState.cpp
T
2018-01-01 17:55:29 +00:00

1448 lines
47 KiB
C++

/******************************************************************************
* The MIT License (MIT)
*
* Copyright (c) 2016-2018 Baldur Karlsson
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
******************************************************************************/
#include <QDebug>
#include "Code/QRDUtils.h"
#include "QRDInterface.h"
rdcstr CommonPipelineState::GetResourceLayout(ResourceId id)
{
if(IsCaptureLoaded())
{
if(IsCaptureVK())
{
for(const VKPipe::ImageData &i : m_Vulkan->images)
{
if(i.resourceId == id)
return i.layouts[0].name;
}
}
if(IsCaptureD3D12())
{
for(const D3D12Pipe::ResourceData &r : m_D3D12->resourceStates)
{
if(r.resourceId == id)
return r.states[0].name;
}
}
}
return lit("Unknown");
}
rdcstr CommonPipelineState::Abbrev(ShaderStage stage)
{
if(IsCaptureD3D11() || (!IsCaptureLoaded() && defaultType == GraphicsAPI::D3D11) ||
IsCaptureD3D12() || (!IsCaptureLoaded() && defaultType == GraphicsAPI::D3D12))
{
switch(stage)
{
case ShaderStage::Vertex: return lit("VS");
case ShaderStage::Hull: return lit("HS");
case ShaderStage::Domain: return lit("DS");
case ShaderStage::Geometry: return lit("GS");
case ShaderStage::Pixel: return lit("PS");
case ShaderStage::Compute: return lit("CS");
default: break;
}
}
else if(IsCaptureGL() || (!IsCaptureLoaded() && defaultType == GraphicsAPI::OpenGL) ||
IsCaptureVK() || (!IsCaptureLoaded() && defaultType == GraphicsAPI::Vulkan))
{
switch(stage)
{
case ShaderStage::Vertex: return lit("VS");
case ShaderStage::Tess_Control: return lit("TCS");
case ShaderStage::Tess_Eval: return lit("TES");
case ShaderStage::Geometry: return lit("GS");
case ShaderStage::Fragment: return lit("FS");
case ShaderStage::Compute: return lit("CS");
default: break;
}
}
return lit("?S");
}
rdcstr CommonPipelineState::OutputAbbrev()
{
if(IsCaptureGL() || (!IsCaptureLoaded() && defaultType == GraphicsAPI::OpenGL) || IsCaptureVK() ||
(!IsCaptureLoaded() && defaultType == GraphicsAPI::Vulkan))
{
return lit("FB");
}
return lit("RT");
}
const D3D11Pipe::Shader &CommonPipelineState::GetD3D11Stage(ShaderStage stage)
{
if(stage == ShaderStage::Vertex)
return m_D3D11->vertexShader;
if(stage == ShaderStage::Domain)
return m_D3D11->domainShader;
if(stage == ShaderStage::Hull)
return m_D3D11->hullShader;
if(stage == ShaderStage::Geometry)
return m_D3D11->geometryShader;
if(stage == ShaderStage::Pixel)
return m_D3D11->pixelShader;
if(stage == ShaderStage::Compute)
return m_D3D11->computeShader;
qCritical() << "Error - invalid stage " << (int)stage;
return m_D3D11->computeShader;
}
const D3D12Pipe::Shader &CommonPipelineState::GetD3D12Stage(ShaderStage stage)
{
if(stage == ShaderStage::Vertex)
return m_D3D12->vertexShader;
if(stage == ShaderStage::Domain)
return m_D3D12->domainShader;
if(stage == ShaderStage::Hull)
return m_D3D12->hullShader;
if(stage == ShaderStage::Geometry)
return m_D3D12->geometryShader;
if(stage == ShaderStage::Pixel)
return m_D3D12->pixelShader;
if(stage == ShaderStage::Compute)
return m_D3D12->computeShader;
qCritical() << "Error - invalid stage " << (int)stage;
return m_D3D12->computeShader;
}
const GLPipe::Shader &CommonPipelineState::GetGLStage(ShaderStage stage)
{
if(stage == ShaderStage::Vertex)
return m_GL->vertexShader;
if(stage == ShaderStage::Tess_Control)
return m_GL->tessControlShader;
if(stage == ShaderStage::Tess_Eval)
return m_GL->tessEvalShader;
if(stage == ShaderStage::Geometry)
return m_GL->geometryShader;
if(stage == ShaderStage::Fragment)
return m_GL->fragmentShader;
if(stage == ShaderStage::Compute)
return m_GL->computeShader;
qCritical() << "Error - invalid stage " << (int)stage;
return m_GL->computeShader;
}
const VKPipe::Shader &CommonPipelineState::GetVulkanStage(ShaderStage stage)
{
if(stage == ShaderStage::Vertex)
return m_Vulkan->vertexShader;
if(stage == ShaderStage::Tess_Control)
return m_Vulkan->tessControlShader;
if(stage == ShaderStage::Tess_Eval)
return m_Vulkan->tessEvalShader;
if(stage == ShaderStage::Geometry)
return m_Vulkan->geometryShader;
if(stage == ShaderStage::Fragment)
return m_Vulkan->fragmentShader;
if(stage == ShaderStage::Compute)
return m_Vulkan->computeShader;
qCritical() << "Error - invalid stage " << (int)stage;
return m_Vulkan->computeShader;
}
rdcstr CommonPipelineState::GetShaderExtension()
{
if(IsCaptureGL() || (!IsCaptureLoaded() && defaultType == GraphicsAPI::OpenGL) || IsCaptureVK() ||
(!IsCaptureLoaded() && defaultType == GraphicsAPI::Vulkan))
{
return lit("glsl");
}
return lit("hlsl");
}
Viewport CommonPipelineState::GetViewport(int index)
{
Viewport ret = {};
if(IsCaptureLoaded())
{
if(IsCaptureD3D11() && index < m_D3D11->rasterizer.viewports.count())
{
return m_D3D11->rasterizer.viewports[index];
}
else if(IsCaptureD3D12() && index < m_D3D12->rasterizer.viewports.count())
{
return m_D3D12->rasterizer.viewports[index];
}
else if(IsCaptureGL() && index < m_GL->rasterizer.viewports.count())
{
return m_GL->rasterizer.viewports[index];
}
else if(IsCaptureVK() && index < m_Vulkan->viewportScissor.viewportScissors.count())
{
return m_Vulkan->viewportScissor.viewportScissors[index].vp;
}
}
return ret;
}
Scissor CommonPipelineState::GetScissor(int index)
{
Scissor ret = {};
if(IsCaptureLoaded())
{
if(IsCaptureD3D11() && index < m_D3D11->rasterizer.viewports.count())
{
return m_D3D11->rasterizer.scissors[index];
}
else if(IsCaptureD3D12() && index < m_D3D12->rasterizer.viewports.count())
{
return m_D3D12->rasterizer.scissors[index];
}
else if(IsCaptureGL() && index < m_GL->rasterizer.viewports.count())
{
return m_GL->rasterizer.scissors[index];
}
else if(IsCaptureVK() && index < m_Vulkan->viewportScissor.viewportScissors.count())
{
return m_Vulkan->viewportScissor.viewportScissors[index].scissor;
}
}
return ret;
}
const ShaderBindpointMapping &CommonPipelineState::GetBindpointMapping(ShaderStage stage)
{
if(IsCaptureLoaded())
{
if(IsCaptureD3D11())
{
switch(stage)
{
case ShaderStage::Vertex: return m_D3D11->vertexShader.bindpointMapping;
case ShaderStage::Domain: return m_D3D11->domainShader.bindpointMapping;
case ShaderStage::Hull: return m_D3D11->hullShader.bindpointMapping;
case ShaderStage::Geometry: return m_D3D11->geometryShader.bindpointMapping;
case ShaderStage::Pixel: return m_D3D11->pixelShader.bindpointMapping;
case ShaderStage::Compute: return m_D3D11->computeShader.bindpointMapping;
default: break;
}
}
else if(IsCaptureD3D12())
{
switch(stage)
{
case ShaderStage::Vertex: return m_D3D12->vertexShader.bindpointMapping;
case ShaderStage::Domain: return m_D3D12->domainShader.bindpointMapping;
case ShaderStage::Hull: return m_D3D12->hullShader.bindpointMapping;
case ShaderStage::Geometry: return m_D3D12->geometryShader.bindpointMapping;
case ShaderStage::Pixel: return m_D3D12->pixelShader.bindpointMapping;
case ShaderStage::Compute: return m_D3D12->computeShader.bindpointMapping;
default: break;
}
}
else if(IsCaptureGL())
{
switch(stage)
{
case ShaderStage::Vertex: return m_GL->vertexShader.bindpointMapping;
case ShaderStage::Tess_Control: return m_GL->tessControlShader.bindpointMapping;
case ShaderStage::Tess_Eval: return m_GL->tessEvalShader.bindpointMapping;
case ShaderStage::Geometry: return m_GL->geometryShader.bindpointMapping;
case ShaderStage::Fragment: return m_GL->fragmentShader.bindpointMapping;
case ShaderStage::Compute: return m_GL->computeShader.bindpointMapping;
default: break;
}
}
else if(IsCaptureVK())
{
switch(stage)
{
case ShaderStage::Vertex: return m_Vulkan->vertexShader.bindpointMapping;
case ShaderStage::Tess_Control: return m_Vulkan->tessControlShader.bindpointMapping;
case ShaderStage::Tess_Eval: return m_Vulkan->tessEvalShader.bindpointMapping;
case ShaderStage::Geometry: return m_Vulkan->geometryShader.bindpointMapping;
case ShaderStage::Fragment: return m_Vulkan->fragmentShader.bindpointMapping;
case ShaderStage::Compute: return m_Vulkan->computeShader.bindpointMapping;
default: break;
}
}
}
static ShaderBindpointMapping empty;
return empty;
}
const ShaderReflection *CommonPipelineState::GetShaderReflection(ShaderStage stage)
{
if(IsCaptureLoaded())
{
if(IsCaptureD3D11())
{
switch(stage)
{
case ShaderStage::Vertex: return m_D3D11->vertexShader.reflection;
case ShaderStage::Domain: return m_D3D11->domainShader.reflection;
case ShaderStage::Hull: return m_D3D11->hullShader.reflection;
case ShaderStage::Geometry: return m_D3D11->geometryShader.reflection;
case ShaderStage::Pixel: return m_D3D11->pixelShader.reflection;
case ShaderStage::Compute: return m_D3D11->computeShader.reflection;
default: break;
}
}
else if(IsCaptureD3D12())
{
switch(stage)
{
case ShaderStage::Vertex: return m_D3D12->vertexShader.reflection;
case ShaderStage::Domain: return m_D3D12->domainShader.reflection;
case ShaderStage::Hull: return m_D3D12->hullShader.reflection;
case ShaderStage::Geometry: return m_D3D12->geometryShader.reflection;
case ShaderStage::Pixel: return m_D3D12->pixelShader.reflection;
case ShaderStage::Compute: return m_D3D12->computeShader.reflection;
default: break;
}
}
else if(IsCaptureGL())
{
switch(stage)
{
case ShaderStage::Vertex: return m_GL->vertexShader.reflection;
case ShaderStage::Tess_Control: return m_GL->tessControlShader.reflection;
case ShaderStage::Tess_Eval: return m_GL->tessEvalShader.reflection;
case ShaderStage::Geometry: return m_GL->geometryShader.reflection;
case ShaderStage::Fragment: return m_GL->fragmentShader.reflection;
case ShaderStage::Compute: return m_GL->computeShader.reflection;
default: break;
}
}
else if(IsCaptureVK())
{
switch(stage)
{
case ShaderStage::Vertex: return m_Vulkan->vertexShader.reflection;
case ShaderStage::Tess_Control: return m_Vulkan->tessControlShader.reflection;
case ShaderStage::Tess_Eval: return m_Vulkan->tessEvalShader.reflection;
case ShaderStage::Geometry: return m_Vulkan->geometryShader.reflection;
case ShaderStage::Fragment: return m_Vulkan->fragmentShader.reflection;
case ShaderStage::Compute: return m_Vulkan->computeShader.reflection;
default: break;
}
}
}
return NULL;
}
ResourceId CommonPipelineState::GetComputePipelineObject()
{
if(IsCaptureLoaded() && IsCaptureVK())
{
return m_Vulkan->compute.pipelineResourceId;
}
else if(IsCaptureLoaded() && IsCaptureD3D12())
{
return m_D3D12->pipelineResourceId;
}
return ResourceId();
}
ResourceId CommonPipelineState::GetGraphicsPipelineObject()
{
if(IsCaptureLoaded() && IsCaptureVK())
{
return m_Vulkan->graphics.pipelineResourceId;
}
else if(IsCaptureLoaded() && IsCaptureD3D12())
{
return m_D3D12->pipelineResourceId;
}
return ResourceId();
}
rdcstr CommonPipelineState::GetShaderEntryPoint(ShaderStage stage)
{
if(IsCaptureLoaded() && IsCaptureVK())
{
switch(stage)
{
case ShaderStage::Vertex: return m_Vulkan->vertexShader.entryPoint;
case ShaderStage::Tess_Control: return m_Vulkan->tessControlShader.entryPoint;
case ShaderStage::Tess_Eval: return m_Vulkan->tessEvalShader.entryPoint;
case ShaderStage::Geometry: return m_Vulkan->geometryShader.entryPoint;
case ShaderStage::Fragment: return m_Vulkan->fragmentShader.entryPoint;
case ShaderStage::Compute: return m_Vulkan->computeShader.entryPoint;
default: break;
}
}
return "";
}
ResourceId CommonPipelineState::GetShader(ShaderStage stage)
{
if(IsCaptureLoaded())
{
if(IsCaptureD3D11())
{
switch(stage)
{
case ShaderStage::Vertex: return m_D3D11->vertexShader.resourceId;
case ShaderStage::Domain: return m_D3D11->domainShader.resourceId;
case ShaderStage::Hull: return m_D3D11->hullShader.resourceId;
case ShaderStage::Geometry: return m_D3D11->geometryShader.resourceId;
case ShaderStage::Pixel: return m_D3D11->pixelShader.resourceId;
case ShaderStage::Compute: return m_D3D11->computeShader.resourceId;
default: break;
}
}
else if(IsCaptureD3D12())
{
switch(stage)
{
case ShaderStage::Vertex: return m_D3D12->vertexShader.resourceId;
case ShaderStage::Domain: return m_D3D12->domainShader.resourceId;
case ShaderStage::Hull: return m_D3D12->hullShader.resourceId;
case ShaderStage::Geometry: return m_D3D12->geometryShader.resourceId;
case ShaderStage::Pixel: return m_D3D12->pixelShader.resourceId;
case ShaderStage::Compute: return m_D3D12->computeShader.resourceId;
default: break;
}
}
else if(IsCaptureGL())
{
switch(stage)
{
case ShaderStage::Vertex: return m_GL->vertexShader.shaderResourceId;
case ShaderStage::Tess_Control: return m_GL->tessControlShader.shaderResourceId;
case ShaderStage::Tess_Eval: return m_GL->tessEvalShader.shaderResourceId;
case ShaderStage::Geometry: return m_GL->geometryShader.shaderResourceId;
case ShaderStage::Fragment: return m_GL->fragmentShader.shaderResourceId;
case ShaderStage::Compute: return m_GL->computeShader.shaderResourceId;
default: break;
}
}
else if(IsCaptureVK())
{
switch(stage)
{
case ShaderStage::Vertex: return m_Vulkan->vertexShader.resourceId;
case ShaderStage::Tess_Control: return m_Vulkan->tessControlShader.resourceId;
case ShaderStage::Tess_Eval: return m_Vulkan->tessEvalShader.resourceId;
case ShaderStage::Geometry: return m_Vulkan->geometryShader.resourceId;
case ShaderStage::Fragment: return m_Vulkan->fragmentShader.resourceId;
case ShaderStage::Compute: return m_Vulkan->computeShader.resourceId;
default: break;
}
}
}
return ResourceId();
}
rdcstr CommonPipelineState::GetShaderName(ShaderStage stage)
{
if(IsCaptureLoaded())
{
if(IsCaptureD3D11())
{
switch(stage)
{
case ShaderStage::Vertex: return m_Ctx.GetResourceName(m_D3D11->vertexShader.resourceId);
case ShaderStage::Domain: return m_Ctx.GetResourceName(m_D3D11->domainShader.resourceId);
case ShaderStage::Hull: return m_Ctx.GetResourceName(m_D3D11->hullShader.resourceId);
case ShaderStage::Geometry:
return m_Ctx.GetResourceName(m_D3D11->geometryShader.resourceId);
case ShaderStage::Pixel: return m_Ctx.GetResourceName(m_D3D11->pixelShader.resourceId);
case ShaderStage::Compute: return m_Ctx.GetResourceName(m_D3D11->computeShader.resourceId);
default: break;
}
}
else if(IsCaptureD3D12())
{
switch(stage)
{
case ShaderStage::Vertex:
return m_Ctx.GetResourceName(m_D3D12->pipelineResourceId) + lit(" VS");
case ShaderStage::Domain:
return m_Ctx.GetResourceName(m_D3D12->pipelineResourceId) + lit(" DS");
case ShaderStage::Hull:
return m_Ctx.GetResourceName(m_D3D12->pipelineResourceId) + lit(" HS");
case ShaderStage::Geometry:
return m_Ctx.GetResourceName(m_D3D12->pipelineResourceId) + lit(" GS");
case ShaderStage::Pixel:
return m_Ctx.GetResourceName(m_D3D12->pipelineResourceId) + lit(" PS");
case ShaderStage::Compute:
return m_Ctx.GetResourceName(m_D3D12->pipelineResourceId) + lit(" CS");
default: break;
}
}
else if(IsCaptureGL())
{
switch(stage)
{
case ShaderStage::Vertex: return m_Ctx.GetResourceName(m_GL->vertexShader.shaderResourceId);
case ShaderStage::Tess_Control:
return m_Ctx.GetResourceName(m_GL->tessControlShader.shaderResourceId);
case ShaderStage::Tess_Eval:
return m_Ctx.GetResourceName(m_GL->tessEvalShader.shaderResourceId);
case ShaderStage::Geometry:
return m_Ctx.GetResourceName(m_GL->geometryShader.shaderResourceId);
case ShaderStage::Fragment:
return m_Ctx.GetResourceName(m_GL->fragmentShader.shaderResourceId);
case ShaderStage::Compute:
return m_Ctx.GetResourceName(m_GL->computeShader.shaderResourceId);
default: break;
}
}
else if(IsCaptureVK())
{
switch(stage)
{
case ShaderStage::Vertex: return m_Ctx.GetResourceName(m_Vulkan->vertexShader.resourceId);
case ShaderStage::Domain:
return m_Ctx.GetResourceName(m_Vulkan->tessControlShader.resourceId);
case ShaderStage::Hull: return m_Ctx.GetResourceName(m_Vulkan->tessEvalShader.resourceId);
case ShaderStage::Geometry:
return m_Ctx.GetResourceName(m_Vulkan->geometryShader.resourceId);
case ShaderStage::Pixel: return m_Ctx.GetResourceName(m_Vulkan->fragmentShader.resourceId);
case ShaderStage::Compute: return m_Ctx.GetResourceName(m_Vulkan->computeShader.resourceId);
default: break;
}
}
}
return "";
}
BoundVBuffer CommonPipelineState::GetIBuffer()
{
ResourceId buf;
uint64_t ByteOffset = 0;
if(IsCaptureLoaded())
{
if(IsCaptureD3D11())
{
buf = m_D3D11->inputAssembly.indexBuffer.resourceId;
ByteOffset = m_D3D11->inputAssembly.indexBuffer.byteOffset;
}
else if(IsCaptureD3D12())
{
buf = m_D3D12->inputAssembly.indexBuffer.resourceId;
ByteOffset = m_D3D12->inputAssembly.indexBuffer.byteOffset;
}
else if(IsCaptureGL())
{
buf = m_GL->vertexInput.indexBuffer;
ByteOffset = 0; // GL only has per-draw index offset
}
else if(IsCaptureVK())
{
buf = m_Vulkan->inputAssembly.indexBuffer.resourceId;
ByteOffset = m_Vulkan->inputAssembly.indexBuffer.byteOffset;
}
}
BoundVBuffer ret;
ret.resourceId = buf;
ret.byteOffset = ByteOffset;
return ret;
}
bool CommonPipelineState::IsStripRestartEnabled()
{
if(IsCaptureLoaded())
{
if(IsCaptureD3D11())
{
// D3D11 this is always enabled
return true;
}
else if(IsCaptureD3D12())
{
return m_D3D12->inputAssembly.indexStripCutValue != 0;
}
else if(IsCaptureGL())
{
return m_GL->vertexInput.primitiveRestart;
}
else if(IsCaptureVK())
{
return m_Vulkan->inputAssembly.primitiveRestartEnable;
}
}
return false;
}
uint32_t CommonPipelineState::GetStripRestartIndex()
{
if(IsCaptureLoaded())
{
if(IsCaptureD3D11() || IsCaptureVK())
{
// D3D11 or Vulkan this is always '-1'
return UINT32_MAX;
}
else if(IsCaptureD3D12())
{
return m_D3D12->inputAssembly.indexStripCutValue;
}
else if(IsCaptureGL())
{
return qMin(UINT32_MAX, m_GL->vertexInput.restartIndex);
}
}
return UINT32_MAX;
}
rdcarray<BoundVBuffer> CommonPipelineState::GetVBuffers()
{
rdcarray<BoundVBuffer> ret;
if(IsCaptureLoaded())
{
if(IsCaptureD3D11())
{
ret.resize(m_D3D11->inputAssembly.vertexBuffers.count());
for(int i = 0; i < m_D3D11->inputAssembly.vertexBuffers.count(); i++)
{
ret[i].resourceId = m_D3D11->inputAssembly.vertexBuffers[i].resourceId;
ret[i].byteOffset = m_D3D11->inputAssembly.vertexBuffers[i].byteOffset;
ret[i].byteStride = m_D3D11->inputAssembly.vertexBuffers[i].byteStride;
}
}
else if(IsCaptureD3D12())
{
ret.resize(m_D3D12->inputAssembly.vertexBuffers.count());
for(int i = 0; i < m_D3D12->inputAssembly.vertexBuffers.count(); i++)
{
ret[i].resourceId = m_D3D12->inputAssembly.vertexBuffers[i].resourceId;
ret[i].byteOffset = m_D3D12->inputAssembly.vertexBuffers[i].byteOffset;
ret[i].byteStride = m_D3D12->inputAssembly.vertexBuffers[i].byteStride;
}
}
else if(IsCaptureGL())
{
ret.resize(m_GL->vertexInput.vertexBuffers.count());
for(int i = 0; i < m_GL->vertexInput.vertexBuffers.count(); i++)
{
ret[i].resourceId = m_GL->vertexInput.vertexBuffers[i].resourceId;
ret[i].byteOffset = m_GL->vertexInput.vertexBuffers[i].byteOffset;
ret[i].byteStride = m_GL->vertexInput.vertexBuffers[i].byteStride;
}
}
else if(IsCaptureVK())
{
ret.resize(m_Vulkan->vertexInput.bindings.count());
for(int i = 0; i < m_Vulkan->vertexInput.bindings.count(); i++)
{
ret[i].resourceId = i < m_Vulkan->vertexInput.vertexBuffers.count()
? m_Vulkan->vertexInput.vertexBuffers[i].resourceId
: ResourceId();
ret[i].byteOffset = i < m_Vulkan->vertexInput.vertexBuffers.count()
? m_Vulkan->vertexInput.vertexBuffers[i].byteOffset
: 0;
ret[i].byteStride = m_Vulkan->vertexInput.bindings[i].byteStride;
}
}
}
return ret;
}
rdcarray<VertexInputAttribute> CommonPipelineState::GetVertexInputs()
{
if(IsCaptureLoaded())
{
if(IsCaptureD3D11())
{
uint32_t byteOffs[128] = {};
const rdcarray<D3D11Pipe::Layout> &layouts = m_D3D11->inputAssembly.layouts;
rdcarray<VertexInputAttribute> ret;
ret.resize(layouts.size());
for(int i = 0; i < layouts.count(); i++)
{
QString semName = layouts[i].semanticName;
bool needsSemanticIdx = false;
for(int j = 0; j < layouts.count(); j++)
{
if(i != j && !semName.compare(layouts[j].semanticName, Qt::CaseInsensitive))
{
needsSemanticIdx = true;
break;
}
}
uint32_t offs = layouts[i].byteOffset;
if(offs == UINT32_MAX) // APPEND_ALIGNED
offs = byteOffs[layouts[i].inputSlot];
else
byteOffs[layouts[i].inputSlot] = offs = layouts[i].byteOffset;
byteOffs[layouts[i].inputSlot] +=
layouts[i].format.compByteWidth * layouts[i].format.compCount;
ret[i].name =
semName + (needsSemanticIdx ? QString::number(layouts[i].semanticIndex) : QString());
ret[i].vertexBuffer = (int)layouts[i].inputSlot;
ret[i].byteOffset = offs;
ret[i].perInstance = layouts[i].perInstance;
ret[i].instanceRate = (int)layouts[i].instanceDataStepRate;
ret[i].format = layouts[i].format;
memset(&ret[i].genericValue, 0, sizeof(PixelValue));
ret[i].used = false;
ret[i].genericEnabled = false;
if(m_D3D11->inputAssembly.bytecode != NULL)
{
rdcarray<SigParameter> &sig = m_D3D11->inputAssembly.bytecode->inputSignature;
for(int ia = 0; ia < sig.count(); ia++)
{
if(!semName.compare(sig[ia].semanticName, Qt::CaseInsensitive) &&
sig[ia].semanticIndex == layouts[i].semanticIndex)
{
ret[i].used = true;
break;
}
}
}
}
return ret;
}
else if(IsCaptureD3D12())
{
uint32_t byteOffs[128] = {};
const rdcarray<D3D12Pipe::Layout> &layouts = m_D3D12->inputAssembly.layouts;
rdcarray<VertexInputAttribute> ret;
ret.resize(layouts.size());
for(int i = 0; i < layouts.count(); i++)
{
QString semName = layouts[i].semanticName;
bool needsSemanticIdx = false;
for(int j = 0; j < layouts.count(); j++)
{
if(i != j && !semName.compare(QString(layouts[j].semanticName), Qt::CaseInsensitive))
{
needsSemanticIdx = true;
break;
}
}
uint32_t offs = layouts[i].byteOffset;
if(offs == UINT32_MAX) // APPEND_ALIGNED
offs = byteOffs[layouts[i].inputSlot];
else
byteOffs[layouts[i].inputSlot] = offs = layouts[i].byteOffset;
byteOffs[layouts[i].inputSlot] +=
layouts[i].format.compByteWidth * layouts[i].format.compCount;
ret[i].name =
semName + (needsSemanticIdx ? QString::number(layouts[i].semanticIndex) : QString());
ret[i].vertexBuffer = (int)layouts[i].inputSlot;
ret[i].byteOffset = offs;
ret[i].perInstance = layouts[i].perInstance;
ret[i].instanceRate = (int)layouts[i].instanceDataStepRate;
ret[i].format = layouts[i].format;
memset(&ret[i].genericValue, 0, sizeof(PixelValue));
ret[i].used = false;
ret[i].genericEnabled = false;
if(m_D3D12->vertexShader.reflection != NULL)
{
rdcarray<SigParameter> &sig = m_D3D12->vertexShader.reflection->inputSignature;
for(int ia = 0; ia < sig.count(); ia++)
{
if(!semName.compare(sig[ia].semanticName, Qt::CaseInsensitive) &&
sig[ia].semanticIndex == layouts[i].semanticIndex)
{
ret[i].used = true;
break;
}
}
}
}
return ret;
}
else if(IsCaptureGL())
{
const rdcarray<GLPipe::VertexAttribute> &attrs = m_GL->vertexInput.attributes;
int num = 0;
for(int i = 0; i < attrs.count(); i++)
{
int attrib = -1;
if(m_GL->vertexShader.reflection != NULL)
attrib = m_GL->vertexShader.bindpointMapping.inputAttributes[i];
else
attrib = i;
if(attrib >= 0)
num++;
}
int a = 0;
rdcarray<VertexInputAttribute> ret;
ret.resize(attrs.count());
for(int i = 0; i < attrs.count() && a < num; i++)
{
ret[a].name = lit("attr%1").arg(i);
memset(&ret[a].genericValue, 0, sizeof(PixelValue));
ret[a].vertexBuffer = (int)attrs[i].vertexBufferSlot;
ret[a].byteOffset = attrs[i].byteOffset;
ret[a].perInstance =
m_GL->vertexInput.vertexBuffers[attrs[i].vertexBufferSlot].instanceDivisor > 0;
ret[a].instanceRate =
(int)m_GL->vertexInput.vertexBuffers[attrs[i].vertexBufferSlot].instanceDivisor;
ret[a].format = attrs[i].format;
ret[a].used = true;
ret[a].genericEnabled = false;
if(m_GL->vertexShader.reflection != NULL)
{
int attrib = m_GL->vertexShader.bindpointMapping.inputAttributes[i];
if(attrib >= 0 && attrib < m_GL->vertexShader.reflection->inputSignature.count())
ret[a].name = m_GL->vertexShader.reflection->inputSignature[attrib].varName;
if(attrib == -1)
continue;
if(!attrs[i].enabled)
{
uint32_t compCount = m_GL->vertexShader.reflection->inputSignature[attrib].compCount;
CompType compType = m_GL->vertexShader.reflection->inputSignature[attrib].compType;
for(uint32_t c = 0; c < compCount; c++)
{
if(compType == CompType::Float)
ret[a].genericValue.floatValue[c] = attrs[i].genericValue.floatValue[c];
else if(compType == CompType::UInt)
ret[a].genericValue.uintValue[c] = attrs[i].genericValue.uintValue[c];
else if(compType == CompType::SInt)
ret[a].genericValue.intValue[c] = attrs[i].genericValue.intValue[c];
else if(compType == CompType::UScaled)
ret[a].genericValue.floatValue[c] = (float)attrs[i].genericValue.uintValue[c];
else if(compType == CompType::SScaled)
ret[a].genericValue.floatValue[c] = (float)attrs[i].genericValue.intValue[c];
}
ret[a].genericEnabled = true;
ret[a].perInstance = false;
ret[a].instanceRate = 0;
ret[a].format.compByteWidth = 4;
ret[a].format.compCount = compCount;
ret[a].format.compType = compType;
ret[a].format.type = ResourceFormatType::Regular;
ret[a].format.srgbCorrected = false;
}
}
a++;
}
return ret;
}
else if(IsCaptureVK())
{
const rdcarray<VKPipe::VertexAttribute> &attrs = m_Vulkan->vertexInput.attributes;
int num = 0;
for(int i = 0; i < attrs.count(); i++)
{
int attrib = -1;
if(m_Vulkan->vertexShader.reflection != NULL)
{
if(attrs[i].location <
(uint32_t)m_Vulkan->vertexShader.bindpointMapping.inputAttributes.count())
attrib = m_Vulkan->vertexShader.bindpointMapping.inputAttributes[attrs[i].location];
}
else
attrib = i;
if(attrib >= 0)
num++;
}
int a = 0;
rdcarray<VertexInputAttribute> ret;
ret.resize(num);
for(int i = 0; i < attrs.count() && a < num; i++)
{
ret[a].name = lit("attr%1").arg(i);
memset(&ret[a].genericValue, 0, sizeof(PixelValue));
ret[a].vertexBuffer = (int)attrs[i].binding;
ret[a].byteOffset = attrs[i].byteOffset;
ret[a].perInstance = false;
if(attrs[i].binding < (uint32_t)m_Vulkan->vertexInput.bindings.count())
ret[a].perInstance = m_Vulkan->vertexInput.bindings[attrs[i].binding].perInstance;
ret[a].instanceRate = 1;
ret[a].format = attrs[i].format;
ret[a].used = true;
ret[a].genericEnabled = false;
if(m_Vulkan->vertexShader.reflection != NULL)
{
int attrib = -1;
if(attrs[i].location <
(uint32_t)m_Vulkan->vertexShader.bindpointMapping.inputAttributes.count())
attrib = m_Vulkan->vertexShader.bindpointMapping.inputAttributes[attrs[i].location];
if(attrib >= 0 && attrib < m_Vulkan->vertexShader.reflection->inputSignature.count())
ret[a].name = m_Vulkan->vertexShader.reflection->inputSignature[attrib].varName;
if(attrib == -1)
continue;
}
a++;
}
return ret;
}
}
return rdcarray<VertexInputAttribute>();
}
BoundCBuffer CommonPipelineState::GetConstantBuffer(ShaderStage stage, uint32_t BufIdx,
uint32_t ArrayIdx)
{
ResourceId buf;
uint64_t ByteOffset = 0;
uint64_t ByteSize = 0;
if(IsCaptureLoaded())
{
if(IsCaptureD3D11())
{
const D3D11Pipe::Shader &s = GetD3D11Stage(stage);
if(s.reflection != NULL && BufIdx < (uint32_t)s.reflection->constantBlocks.count())
{
const Bindpoint &bind =
s.bindpointMapping.constantBlocks[s.reflection->constantBlocks[BufIdx].bindPoint];
if(bind.bind >= s.constantBuffers.count())
return BoundCBuffer();
const D3D11Pipe::ConstantBuffer &descriptor = s.constantBuffers[bind.bind];
buf = descriptor.resourceId;
ByteOffset = descriptor.vecOffset * 4 * sizeof(float);
ByteSize = descriptor.vecCount * 4 * sizeof(float);
}
}
else if(IsCaptureD3D12())
{
const D3D12Pipe::Shader &s = GetD3D12Stage(stage);
if(s.reflection != NULL && BufIdx < (uint32_t)s.reflection->constantBlocks.count())
{
const Bindpoint &bind =
s.bindpointMapping.constantBlocks[s.reflection->constantBlocks[BufIdx].bindPoint];
if(bind.bindset >= s.spaces.count() ||
bind.bind >= s.spaces[bind.bindset].constantBuffers.count())
return BoundCBuffer();
const D3D12Pipe::ConstantBuffer &descriptor =
s.spaces[bind.bindset].constantBuffers[bind.bind];
buf = descriptor.resourceId;
ByteOffset = descriptor.byteOffset;
ByteSize = descriptor.byteSize;
}
}
else if(IsCaptureGL())
{
const GLPipe::Shader &s = GetGLStage(stage);
if(s.reflection != NULL && BufIdx < (uint32_t)s.reflection->constantBlocks.count())
{
if(s.reflection->constantBlocks[BufIdx].bindPoint >= 0)
{
int uboIdx =
s.bindpointMapping.constantBlocks[s.reflection->constantBlocks[BufIdx].bindPoint].bind;
if(uboIdx >= 0 && uboIdx < m_GL->uniformBuffers.count())
{
const GLPipe::Buffer &b = m_GL->uniformBuffers[uboIdx];
buf = b.resourceId;
ByteOffset = b.byteOffset;
ByteSize = b.byteSize;
}
}
}
}
else if(IsCaptureVK())
{
const VKPipe::Pipeline &pipe =
stage == ShaderStage::Compute ? m_Vulkan->compute : m_Vulkan->graphics;
const VKPipe::Shader &s = GetVulkanStage(stage);
if(s.reflection != NULL && BufIdx < (uint32_t)s.reflection->constantBlocks.count())
{
const Bindpoint &bind =
s.bindpointMapping.constantBlocks[s.reflection->constantBlocks[BufIdx].bindPoint];
if(s.reflection->constantBlocks[BufIdx].bufferBacked == false)
{
BoundCBuffer ret;
// dummy value, it would be nice to fetch this properly
ret.byteSize = 1024;
return ret;
}
const VKPipe::BindingElement &descriptorBind =
pipe.descriptorSets[bind.bindset].bindings[bind.bind].binds[ArrayIdx];
buf = descriptorBind.resourceResourceId;
ByteOffset = descriptorBind.byteOffset;
ByteSize = descriptorBind.byteSize;
}
}
}
BoundCBuffer ret;
ret.resourceId = buf;
ret.byteOffset = ByteOffset;
ret.byteSize = ByteSize;
return ret;
}
rdcarray<BoundResourceArray> CommonPipelineState::GetReadOnlyResources(ShaderStage stage)
{
rdcarray<BoundResourceArray> ret;
if(IsCaptureLoaded())
{
if(IsCaptureD3D11())
{
const D3D11Pipe::Shader &s = GetD3D11Stage(stage);
ret.reserve(s.srvs.size());
for(int i = 0; i < s.srvs.count(); i++)
{
Bindpoint key(0, i);
BoundResource val;
val.resourceId = s.srvs[i].resourceResourceId;
val.firstMip = (int)s.srvs[i].firstMip;
val.firstSlice = (int)s.srvs[i].firstSlice;
val.typeHint = s.srvs[i].viewFormat.compType;
ret.push_back(BoundResourceArray(key, {val}));
}
return ret;
}
else if(IsCaptureD3D12())
{
const D3D12Pipe::Shader &s = GetD3D12Stage(stage);
for(int space = 0; space < s.spaces.count(); space++)
{
for(int reg = 0; reg < s.spaces[space].srvs.count(); reg++)
{
const D3D12Pipe::View &bind = s.spaces[space].srvs[reg];
Bindpoint key(space, reg);
BoundResource val;
// consider this register to not exist - it's in a gap defined by sparse root signature
// elements
if(bind.rootElement == ~0U)
continue;
val.resourceId = bind.resourceId;
val.firstMip = (int)bind.firstMip;
val.firstSlice = (int)bind.firstSlice;
val.typeHint = bind.viewFormat.compType;
ret.push_back(BoundResourceArray(key, {val}));
}
}
return ret;
}
else if(IsCaptureGL())
{
ret.reserve(m_GL->textures.size());
for(int i = 0; i < m_GL->textures.count(); i++)
{
Bindpoint key(0, i);
BoundResource val;
val.resourceId = m_GL->textures[i].resourceId;
val.firstMip = (int)m_GL->textures[i].firstMip;
val.firstSlice = (int)m_GL->textures[i].firstSlice;
val.typeHint = CompType::Typeless;
ret.push_back(BoundResourceArray(key, {val}));
}
return ret;
}
else if(IsCaptureVK())
{
const rdcarray<VKPipe::DescriptorSet> &descsets = stage == ShaderStage::Compute
? m_Vulkan->compute.descriptorSets
: m_Vulkan->graphics.descriptorSets;
ShaderStageMask mask = MaskForStage(stage);
for(int set = 0; set < descsets.count(); set++)
{
const VKPipe::DescriptorSet &descset = descsets[set];
for(int slot = 0; slot < descset.bindings.count(); slot++)
{
const VKPipe::DescriptorBinding &bind = descset.bindings[slot];
if((bind.type == BindType::ImageSampler || bind.type == BindType::InputAttachment ||
bind.type == BindType::ReadOnlyImage || bind.type == BindType::ReadOnlyTBuffer) &&
(bind.stageFlags & mask) == mask)
{
ret.push_back(BoundResourceArray());
ret.back().bindPoint = Bindpoint(set, slot);
rdcarray<BoundResource> &val = ret.back().resources;
val.resize(bind.descriptorCount);
for(uint32_t i = 0; i < bind.descriptorCount; i++)
{
val[i].resourceId = bind.binds[i].resourceResourceId;
val[i].firstMip = (int)bind.binds[i].firstMip;
val[i].firstSlice = (int)bind.binds[i].firstSlice;
val[i].typeHint = bind.binds[i].viewFormat.compType;
}
}
}
}
return ret;
}
}
return ret;
}
rdcarray<BoundResourceArray> CommonPipelineState::GetReadWriteResources(ShaderStage stage)
{
rdcarray<BoundResourceArray> ret;
if(IsCaptureLoaded())
{
if(IsCaptureD3D11())
{
if(stage == ShaderStage::Compute)
{
ret.reserve(m_D3D11->computeShader.uavs.size());
for(int i = 0; i < m_D3D11->computeShader.uavs.count(); i++)
{
Bindpoint key(0, i);
BoundResource val;
val.resourceId = m_D3D11->computeShader.uavs[i].resourceResourceId;
val.firstMip = (int)m_D3D11->computeShader.uavs[i].firstMip;
val.firstSlice = (int)m_D3D11->computeShader.uavs[i].firstSlice;
val.typeHint = m_D3D11->computeShader.uavs[i].viewFormat.compType;
ret.push_back(BoundResourceArray(key, {val}));
}
}
else
{
int uavstart = (int)m_D3D11->outputMerger.uavStartSlot;
ret.reserve(m_D3D11->outputMerger.uavs.size() + qMax(0, uavstart));
// up to UAVStartSlot treat these bindings as empty.
for(int i = 0; i < uavstart; i++)
{
Bindpoint key(0, i);
BoundResource val;
ret.push_back(BoundResourceArray(key, {val}));
}
for(int i = 0; i < m_D3D11->outputMerger.uavs.count() - uavstart; i++)
{
Bindpoint key(0, i + uavstart);
BoundResource val;
val.resourceId = m_D3D11->outputMerger.uavs[i].resourceResourceId;
val.firstMip = (int)m_D3D11->outputMerger.uavs[i].firstMip;
val.firstSlice = (int)m_D3D11->outputMerger.uavs[i].firstSlice;
val.typeHint = m_D3D11->outputMerger.uavs[i].viewFormat.compType;
ret.push_back(BoundResourceArray(key, {val}));
}
}
}
else if(IsCaptureD3D12())
{
const D3D12Pipe::Shader &s = GetD3D12Stage(stage);
for(int space = 0; space < s.spaces.count(); space++)
{
for(int reg = 0; reg < s.spaces[space].uavs.count(); reg++)
{
const D3D12Pipe::View &bind = s.spaces[space].uavs[reg];
Bindpoint key(space, reg);
BoundResource val;
// consider this register to not exist - it's in a gap defined by sparse root signature
// elements
if(bind.rootElement == ~0U)
continue;
val.resourceId = bind.resourceId;
val.firstMip = (int)bind.firstMip;
val.firstSlice = (int)bind.firstSlice;
val.typeHint = bind.viewFormat.compType;
ret.push_back(BoundResourceArray(key, {val}));
}
}
}
else if(IsCaptureGL())
{
ret.reserve(m_GL->images.size());
for(int i = 0; i < m_GL->images.count(); i++)
{
Bindpoint key(0, i);
BoundResource val;
val.resourceId = m_GL->images[i].resourceId;
val.firstMip = (int)m_GL->images[i].mipLevel;
val.firstSlice = (int)m_GL->images[i].slice;
val.typeHint = m_GL->images[i].imageFormat.compType;
ret.push_back(BoundResourceArray(key, {val}));
}
}
else if(IsCaptureVK())
{
const rdcarray<VKPipe::DescriptorSet> &descsets = stage == ShaderStage::Compute
? m_Vulkan->compute.descriptorSets
: m_Vulkan->graphics.descriptorSets;
ShaderStageMask mask = MaskForStage(stage);
for(int set = 0; set < descsets.count(); set++)
{
const VKPipe::DescriptorSet &descset = descsets[set];
for(int slot = 0; slot < descset.bindings.count(); slot++)
{
const VKPipe::DescriptorBinding &bind = descset.bindings[slot];
if((bind.type == BindType::ReadWriteBuffer || bind.type == BindType::ReadWriteImage ||
bind.type == BindType::ReadWriteTBuffer) &&
(bind.stageFlags & mask) == mask)
{
ret.push_back(BoundResourceArray());
ret.back().bindPoint = Bindpoint(set, slot);
rdcarray<BoundResource> &val = ret.back().resources;
val.resize(bind.descriptorCount);
for(uint32_t i = 0; i < bind.descriptorCount; i++)
{
val[i].resourceId = bind.binds[i].resourceResourceId;
val[i].firstMip = (int)bind.binds[i].firstMip;
val[i].firstSlice = (int)bind.binds[i].firstSlice;
val[i].typeHint = bind.binds[i].viewFormat.compType;
}
}
}
}
}
}
return ret;
}
BoundResource CommonPipelineState::GetDepthTarget()
{
if(IsCaptureLoaded())
{
if(IsCaptureD3D11())
{
BoundResource ret;
ret.resourceId = m_D3D11->outputMerger.depthTarget.resourceResourceId;
ret.firstMip = (int)m_D3D11->outputMerger.depthTarget.firstMip;
ret.firstSlice = (int)m_D3D11->outputMerger.depthTarget.firstSlice;
ret.typeHint = m_D3D11->outputMerger.depthTarget.viewFormat.compType;
return ret;
}
else if(IsCaptureD3D12())
{
BoundResource ret;
ret.resourceId = m_D3D12->outputMerger.depthTarget.resourceId;
ret.firstMip = (int)m_D3D12->outputMerger.depthTarget.firstMip;
ret.firstSlice = (int)m_D3D12->outputMerger.depthTarget.firstSlice;
ret.typeHint = m_D3D12->outputMerger.depthTarget.viewFormat.compType;
return ret;
}
else if(IsCaptureGL())
{
BoundResource ret;
ret.resourceId = m_GL->framebuffer.drawFBO.depthAttachment.resourceId;
ret.firstMip = (int)m_GL->framebuffer.drawFBO.depthAttachment.mipLevel;
ret.firstSlice = (int)m_GL->framebuffer.drawFBO.depthAttachment.slice;
ret.typeHint = CompType::Typeless;
return ret;
}
else if(IsCaptureVK())
{
const VKPipe::RenderPass &rp = m_Vulkan->currentPass.renderpass;
const VKPipe::Framebuffer &fb = m_Vulkan->currentPass.framebuffer;
if(rp.depthstencilAttachment >= 0 && rp.depthstencilAttachment < fb.attachments.count())
{
BoundResource ret;
ret.resourceId = fb.attachments[rp.depthstencilAttachment].imageResourceId;
ret.firstMip = (int)fb.attachments[rp.depthstencilAttachment].firstMip;
ret.firstSlice = (int)fb.attachments[rp.depthstencilAttachment].firstSlice;
ret.typeHint = fb.attachments[rp.depthstencilAttachment].viewFormat.compType;
return ret;
}
return BoundResource();
}
}
return BoundResource();
}
rdcarray<BoundResource> CommonPipelineState::GetOutputTargets()
{
rdcarray<BoundResource> ret;
if(IsCaptureLoaded())
{
if(IsCaptureD3D11())
{
ret.resize(m_D3D11->outputMerger.renderTargets.count());
for(int i = 0; i < m_D3D11->outputMerger.renderTargets.count(); i++)
{
ret[i].resourceId = m_D3D11->outputMerger.renderTargets[i].resourceResourceId;
ret[i].firstMip = (int)m_D3D11->outputMerger.renderTargets[i].firstMip;
ret[i].firstSlice = (int)m_D3D11->outputMerger.renderTargets[i].firstSlice;
ret[i].typeHint = m_D3D11->outputMerger.renderTargets[i].viewFormat.compType;
}
}
else if(IsCaptureD3D12())
{
ret.resize(m_D3D12->outputMerger.renderTargets.count());
for(int i = 0; i < m_D3D12->outputMerger.renderTargets.count(); i++)
{
ret[i].resourceId = m_D3D12->outputMerger.renderTargets[i].resourceId;
ret[i].firstMip = (int)m_D3D12->outputMerger.renderTargets[i].firstMip;
ret[i].firstSlice = (int)m_D3D12->outputMerger.renderTargets[i].firstSlice;
ret[i].typeHint = m_D3D12->outputMerger.renderTargets[i].viewFormat.compType;
}
}
else if(IsCaptureGL())
{
ret.resize(m_GL->framebuffer.drawFBO.drawBuffers.count());
for(int i = 0; i < m_GL->framebuffer.drawFBO.drawBuffers.count(); i++)
{
int db = m_GL->framebuffer.drawFBO.drawBuffers[i];
if(db >= 0)
{
ret[i].resourceId = m_GL->framebuffer.drawFBO.colorAttachments[db].resourceId;
ret[i].firstMip = (int)m_GL->framebuffer.drawFBO.colorAttachments[db].mipLevel;
ret[i].firstSlice = (int)m_GL->framebuffer.drawFBO.colorAttachments[db].slice;
ret[i].typeHint = CompType::Typeless;
}
}
}
else if(IsCaptureVK())
{
const VKPipe::RenderPass &rp = m_Vulkan->currentPass.renderpass;
const VKPipe::Framebuffer &fb = m_Vulkan->currentPass.framebuffer;
int idx = 0;
ret.resize(rp.colorAttachments.count() + rp.resolveAttachments.count());
for(int i = 0; i < rp.colorAttachments.count(); i++)
{
if(rp.colorAttachments[i] < (uint32_t)fb.attachments.count())
{
ret[idx].resourceId = fb.attachments[rp.colorAttachments[i]].imageResourceId;
ret[idx].firstMip = (int)fb.attachments[rp.colorAttachments[i]].firstMip;
ret[idx].firstSlice = (int)fb.attachments[rp.colorAttachments[i]].firstSlice;
ret[idx].typeHint = fb.attachments[rp.colorAttachments[i]].viewFormat.compType;
}
idx++;
}
for(int i = 0; i < rp.resolveAttachments.count(); i++)
{
if(rp.resolveAttachments[i] < (uint32_t)fb.attachments.count())
{
ret[idx].resourceId = fb.attachments[rp.resolveAttachments[i]].imageResourceId;
ret[idx].firstMip = (int)fb.attachments[rp.resolveAttachments[i]].firstMip;
ret[idx].firstSlice = (int)fb.attachments[rp.resolveAttachments[i]].firstSlice;
ret[idx].typeHint = fb.attachments[rp.resolveAttachments[i]].viewFormat.compType;
}
idx++;
}
}
}
return ret;
}