mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-07-30 19:31:07 +00:00
Vk Pixel History: multi sampled colour
Colour only, depth/stencil copy not supported. This means that we only report pre-mod and post-mod colour values for events. Since stencil copy is not supported, number of fragments is not reported, and shader output is not queried.
This commit is contained in:
committed by
Baldur Karlsson
parent
ccab431cd1
commit
2cb546686b
@@ -70,9 +70,18 @@ uniform ivec4 mscopy;
|
||||
void main()
|
||||
{
|
||||
ivec3 id = ivec3(gl_GlobalInvocationID);
|
||||
|
||||
int slice = int(id.z / numMultiSamples);
|
||||
int sampleIdx = int(id.z % numMultiSamples);
|
||||
int slice;
|
||||
int sampleIdx;
|
||||
if(numMultiSamples == 0)
|
||||
{
|
||||
slice = currentSlice;
|
||||
sampleIdx = currentSample;
|
||||
}
|
||||
else
|
||||
{
|
||||
slice = int(id.z / numMultiSamples);
|
||||
sampleIdx = int(id.z % numMultiSamples);
|
||||
}
|
||||
|
||||
uvec4 data = texelFetch(srcMS, ivec3(int(id.x), int(id.y), slice), sampleIdx);
|
||||
|
||||
|
||||
@@ -1714,6 +1714,10 @@ void VulkanReplay::CreateResources()
|
||||
|
||||
m_PixelPick.Init(m_pDriver, m_General.DescriptorPool);
|
||||
|
||||
RenderDoc::Inst().SetProgress(LoadProgress::DebugManagerInit, 0.75f);
|
||||
|
||||
m_PixelHistory.Init(m_pDriver, m_General.DescriptorPool);
|
||||
|
||||
RenderDoc::Inst().SetProgress(LoadProgress::DebugManagerInit, 0.8f);
|
||||
|
||||
m_Histogram.Init(m_pDriver, m_General.DescriptorPool);
|
||||
@@ -1765,6 +1769,7 @@ void VulkanReplay::DestroyResources()
|
||||
m_Overlay.Destroy(m_pDriver);
|
||||
m_VertexPick.Destroy(m_pDriver);
|
||||
m_PixelPick.Destroy(m_pDriver);
|
||||
m_PixelHistory.Destroy(m_pDriver);
|
||||
m_Histogram.Destroy(m_pDriver);
|
||||
m_PostVS.Destroy(m_pDriver);
|
||||
|
||||
@@ -2594,6 +2599,23 @@ void VulkanReplay::PixelPicking::Destroy(WrappedVulkan *driver)
|
||||
driver->vkDestroyRenderPass(driver->GetDev(), RP, NULL);
|
||||
}
|
||||
|
||||
void VulkanReplay::PixelHistory::Init(WrappedVulkan *driver, VkDescriptorPool descriptorPool)
|
||||
{
|
||||
CREATE_OBJECT(MSCopyDescSetLayout,
|
||||
{
|
||||
{0, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_ALL, NULL},
|
||||
{1, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_ALL, NULL},
|
||||
{2, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1, VK_SHADER_STAGE_ALL, NULL},
|
||||
});
|
||||
CREATE_OBJECT(MSCopyDescSet, descriptorPool, MSCopyDescSetLayout);
|
||||
}
|
||||
|
||||
void VulkanReplay::PixelHistory::Destroy(WrappedVulkan *driver)
|
||||
{
|
||||
if(MSCopyDescSetLayout != VK_NULL_HANDLE)
|
||||
driver->vkDestroyDescriptorSetLayout(driver->GetDev(), MSCopyDescSetLayout, NULL);
|
||||
}
|
||||
|
||||
void VulkanReplay::HistogramMinMax::Init(WrappedVulkan *driver, VkDescriptorPool descriptorPool)
|
||||
{
|
||||
VulkanShaderCache *shaderCache = driver->GetShaderCache();
|
||||
|
||||
@@ -68,6 +68,8 @@ public:
|
||||
uint32_t samples, VkFormat fmt);
|
||||
void CopyArrayToTex2DMS(VkImage destMS, VkImage srcArray, VkExtent3D extent, uint32_t layers,
|
||||
uint32_t samples, VkFormat fmt);
|
||||
void CopyTex2DMSPixel(VkCommandBuffer cmd, VkDescriptorSet descSet, VkExtent3D extent,
|
||||
uint32_t sample, VkFormat fmt);
|
||||
|
||||
VkPipelineCache GetPipelineCache() { return m_PipelineCache; }
|
||||
VkPipeline GetCustomPipeline() { return m_Custom.TexPipeline; }
|
||||
@@ -86,8 +88,9 @@ public:
|
||||
void PatchLineStripIndexBuffer(const DrawcallDescription *draw, GPUBuffer &indexBuffer,
|
||||
uint32_t &indexCount);
|
||||
|
||||
bool PixelHistorySetupResources(PixelHistoryResources &resources, VkExtent3D extent,
|
||||
VkFormat format, uint32_t numEvents);
|
||||
bool PixelHistorySetupResources(PixelHistoryResources &resources, VkImage targetImage,
|
||||
VkExtent3D extent, VkFormat format, VkSampleCountFlagBits samples,
|
||||
const Subresource &sub, uint32_t numEvents);
|
||||
bool PixelHistoryDestroyResources(const PixelHistoryResources &resources);
|
||||
|
||||
void PixelHistoryCopyPixel(VkCommandBuffer cmd, CopyPixelParams &p, size_t offset);
|
||||
@@ -114,13 +117,11 @@ private:
|
||||
|
||||
// CopyArrayToTex2DMS & CopyTex2DMSToArray
|
||||
VkDescriptorPool m_ArrayMSDescriptorPool;
|
||||
|
||||
VkDescriptorSetLayout m_ArrayMSDescSetLayout = VK_NULL_HANDLE;
|
||||
VkPipelineLayout m_ArrayMSPipeLayout = VK_NULL_HANDLE;
|
||||
VkDescriptorSet m_ArrayMSDescSet = VK_NULL_HANDLE;
|
||||
VkPipeline m_Array2MSPipe = VK_NULL_HANDLE;
|
||||
VkPipeline m_MS2ArrayPipe = VK_NULL_HANDLE;
|
||||
|
||||
VkSampler m_ArrayMSSampler = VK_NULL_HANDLE;
|
||||
|
||||
// [0] = non-MSAA, [1] = MSAA
|
||||
|
||||
@@ -146,6 +146,27 @@ void VulkanDebugManager::CopyTex2DMSToArray(VkImage destArray, VkImage srcMS, Vk
|
||||
ObjDisp(dev)->DestroyImageView(Unwrap(dev), destView, NULL);
|
||||
}
|
||||
|
||||
void VulkanDebugManager::CopyTex2DMSPixel(VkCommandBuffer cmd, VkDescriptorSet descSet,
|
||||
VkExtent3D extent, uint32_t sample, VkFormat fmt)
|
||||
{
|
||||
if(!m_pDriver->GetDeviceFeatures().shaderStorageImageWriteWithoutFormat)
|
||||
return;
|
||||
|
||||
if(m_MS2ArrayPipe == VK_NULL_HANDLE)
|
||||
return;
|
||||
|
||||
ObjDisp(cmd)->CmdBindPipeline(Unwrap(cmd), VK_PIPELINE_BIND_POINT_COMPUTE, Unwrap(m_MS2ArrayPipe));
|
||||
ObjDisp(cmd)->CmdBindDescriptorSets(Unwrap(cmd), VK_PIPELINE_BIND_POINT_COMPUTE,
|
||||
Unwrap(m_ArrayMSPipeLayout), 0, 1, UnwrapPtr(descSet), 0, NULL);
|
||||
|
||||
Vec4u params = {0, sample, 0, 0};
|
||||
|
||||
ObjDisp(cmd)->CmdPushConstants(Unwrap(cmd), Unwrap(m_ArrayMSPipeLayout), VK_SHADER_STAGE_ALL, 0,
|
||||
sizeof(Vec4u), ¶ms);
|
||||
// TODO: Specify a single pixel to copy.
|
||||
ObjDisp(cmd)->CmdDispatch(Unwrap(cmd), extent.width, extent.height, 1);
|
||||
}
|
||||
|
||||
void VulkanDebugManager::CopyDepthTex2DMSToArray(VkImage destArray, VkImage srcMS, VkExtent3D extent,
|
||||
uint32_t layers, uint32_t samples, VkFormat fmt)
|
||||
{
|
||||
|
||||
@@ -60,21 +60,11 @@ enum
|
||||
|
||||
struct CopyPixelParams
|
||||
{
|
||||
bool multisampled;
|
||||
bool floatTex;
|
||||
bool uintTex;
|
||||
bool intTex;
|
||||
|
||||
bool depthCopy;
|
||||
bool stencilOnly;
|
||||
VkImage srcImage;
|
||||
VkFormat srcImageFormat;
|
||||
VkImageLayout srcImageLayout;
|
||||
VkOffset3D imageOffset;
|
||||
uint32_t slice;
|
||||
uint32_t mipLevel;
|
||||
|
||||
VkBuffer dstBuffer;
|
||||
};
|
||||
|
||||
struct PixelHistoryResources
|
||||
@@ -88,6 +78,13 @@ struct PixelHistoryResources
|
||||
VkImage stencilImage;
|
||||
VkImageView stencilImageView;
|
||||
VkDeviceMemory gpuMem;
|
||||
|
||||
// Following are only used and created for multi sampled images.
|
||||
VkImage stagingImage;
|
||||
VkImageView stagingImageView;
|
||||
VkImage stencilStagingImage;
|
||||
VkImageView stencilStagingImageView;
|
||||
VkImageView targetImageView;
|
||||
};
|
||||
|
||||
struct PixelHistoryCallbackInfo
|
||||
@@ -99,6 +96,7 @@ struct PixelHistoryCallbackInfo
|
||||
uint32_t layers;
|
||||
uint32_t mipLevels;
|
||||
VkSampleCountFlagBits samples;
|
||||
VkExtent3D extent;
|
||||
// Information about the location of the pixel for which history was requested.
|
||||
Subresource targetSubresource;
|
||||
uint32_t x;
|
||||
@@ -113,6 +111,10 @@ struct PixelHistoryCallbackInfo
|
||||
VkImage stencilImage;
|
||||
VkImageView stencilImageView;
|
||||
|
||||
// Only used for multi sampled images for copy into a staging resource.
|
||||
VkImage stagingImage;
|
||||
VkImage stencilStagingImage;
|
||||
|
||||
// Buffer used to copy colour and depth information
|
||||
VkBuffer dstBuffer;
|
||||
};
|
||||
@@ -592,7 +594,7 @@ protected:
|
||||
|
||||
VkAttachmentDescription dsAtt = {};
|
||||
dsAtt.format = VK_FORMAT_D32_SFLOAT_S8_UINT;
|
||||
dsAtt.samples = VK_SAMPLE_COUNT_1_BIT;
|
||||
dsAtt.samples = m_CallbackInfo.samples;
|
||||
dsAtt.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
||||
dsAtt.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
||||
dsAtt.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
|
||||
@@ -689,6 +691,122 @@ protected:
|
||||
return framebuffer;
|
||||
}
|
||||
|
||||
void CopyImagePixel(VkCommandBuffer cmd, CopyPixelParams &p, size_t offset)
|
||||
{
|
||||
rdcarray<VkBufferImageCopy> regions;
|
||||
VkImageAspectFlags aspectFlags = 0;
|
||||
VkBufferImageCopy region = {};
|
||||
region.bufferOffset = (uint64_t)offset;
|
||||
region.bufferRowLength = 0;
|
||||
region.bufferImageHeight = 0;
|
||||
region.imageOffset.x = m_CallbackInfo.x;
|
||||
region.imageOffset.y = m_CallbackInfo.y;
|
||||
region.imageOffset.z = 0;
|
||||
region.imageExtent.width = 1U;
|
||||
region.imageExtent.height = 1U;
|
||||
region.imageExtent.depth = 1U;
|
||||
region.imageSubresource.baseArrayLayer = m_CallbackInfo.targetSubresource.slice;
|
||||
region.imageSubresource.mipLevel = m_CallbackInfo.targetSubresource.mip;
|
||||
region.imageSubresource.layerCount = 1;
|
||||
|
||||
// TODO: support depth/stencil copy for multi-sampled images.
|
||||
if(p.depthCopy && (m_CallbackInfo.samples != VK_SAMPLE_COUNT_1_BIT))
|
||||
return;
|
||||
|
||||
if(!p.depthCopy)
|
||||
{
|
||||
region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
regions.push_back(region);
|
||||
aspectFlags = VkImageAspectFlags(VK_IMAGE_ASPECT_COLOR_BIT);
|
||||
}
|
||||
else if(p.stencilOnly)
|
||||
{
|
||||
region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT;
|
||||
regions.push_back(region);
|
||||
aspectFlags = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
|
||||
}
|
||||
else
|
||||
{
|
||||
region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
|
||||
if(IsDepthOnlyFormat(p.srcImageFormat) || IsDepthAndStencilFormat(p.srcImageFormat))
|
||||
{
|
||||
regions.push_back(region);
|
||||
aspectFlags |= VK_IMAGE_ASPECT_DEPTH_BIT;
|
||||
}
|
||||
if(IsStencilFormat(p.srcImageFormat))
|
||||
{
|
||||
region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT;
|
||||
region.bufferOffset = offset + 4;
|
||||
regions.push_back(region);
|
||||
aspectFlags |= VK_IMAGE_ASPECT_STENCIL_BIT;
|
||||
}
|
||||
}
|
||||
|
||||
VkImage cmdCopySource = p.srcImage;
|
||||
VkImageLayout cmdCopySourceLayout = p.srcImageLayout;
|
||||
uint32_t baseArrayLayer = m_CallbackInfo.targetSubresource.slice;
|
||||
|
||||
// For multi-sampled images can't call vkCmdCopyImageToBuffer directly,
|
||||
// copy using a compute shader into a staging image first.
|
||||
if(m_CallbackInfo.samples != VK_SAMPLE_COUNT_1_BIT)
|
||||
{
|
||||
regions[0].imageSubresource.baseArrayLayer = 0;
|
||||
VkImageMemoryBarrier barrier = {VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
|
||||
NULL,
|
||||
VK_ACCESS_SHADER_WRITE_BIT |
|
||||
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
|
||||
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT |
|
||||
VK_ACCESS_TRANSFER_WRITE_BIT | VK_ACCESS_MEMORY_WRITE_BIT,
|
||||
VK_ACCESS_SHADER_READ_BIT,
|
||||
p.srcImageLayout,
|
||||
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
|
||||
VK_QUEUE_FAMILY_IGNORED,
|
||||
VK_QUEUE_FAMILY_IGNORED,
|
||||
Unwrap(p.srcImage),
|
||||
{aspectFlags, 0, 1, baseArrayLayer, 1}};
|
||||
|
||||
DoPipelineBarrier(cmd, 1, &barrier);
|
||||
m_pDriver->GetReplay()->CopyPixelForPixelHistory(cmd, m_CallbackInfo.extent,
|
||||
m_CallbackInfo.targetSubresource.sample,
|
||||
m_CallbackInfo.targetImageFormat);
|
||||
|
||||
barrier.srcAccessMask = VK_ACCESS_SHADER_READ_BIT;
|
||||
barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
|
||||
barrier.oldLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
||||
barrier.newLayout = p.srcImageLayout;
|
||||
DoPipelineBarrier(cmd, 1, &barrier);
|
||||
|
||||
cmdCopySource = m_CallbackInfo.stagingImage;
|
||||
cmdCopySourceLayout = VK_IMAGE_LAYOUT_GENERAL;
|
||||
baseArrayLayer = 0;
|
||||
}
|
||||
|
||||
VkImageMemoryBarrier barrier = {VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
|
||||
NULL,
|
||||
VK_ACCESS_SHADER_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
|
||||
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT |
|
||||
VK_ACCESS_TRANSFER_WRITE_BIT | VK_ACCESS_MEMORY_WRITE_BIT,
|
||||
VK_ACCESS_TRANSFER_READ_BIT,
|
||||
cmdCopySourceLayout,
|
||||
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
|
||||
VK_QUEUE_FAMILY_IGNORED,
|
||||
VK_QUEUE_FAMILY_IGNORED,
|
||||
Unwrap(cmdCopySource),
|
||||
{aspectFlags, 0, 1, baseArrayLayer, 1}};
|
||||
|
||||
DoPipelineBarrier(cmd, 1, &barrier);
|
||||
|
||||
ObjDisp(cmd)->CmdCopyImageToBuffer(
|
||||
Unwrap(cmd), Unwrap(cmdCopySource), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
|
||||
Unwrap(m_CallbackInfo.dstBuffer), (uint32_t)regions.size(), regions.data());
|
||||
|
||||
barrier.srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
|
||||
barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
|
||||
barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
|
||||
barrier.newLayout = cmdCopySourceLayout;
|
||||
DoPipelineBarrier(cmd, 1, &barrier);
|
||||
}
|
||||
|
||||
WrappedVulkan *m_pDriver;
|
||||
PixelHistoryShaderCache *m_ShaderCache;
|
||||
PixelHistoryCallbackInfo m_CallbackInfo;
|
||||
@@ -947,30 +1065,21 @@ struct VulkanColorAndStencilCallback : public VulkanPixelHistoryCallback
|
||||
ReplayDraw(cmd, eid, true);
|
||||
|
||||
CopyPixelParams params = {};
|
||||
params.multisampled = false;
|
||||
params.srcImage = m_CallbackInfo.stencilImage;
|
||||
params.srcImageLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
|
||||
params.srcImageFormat = VK_FORMAT_D32_SFLOAT_S8_UINT;
|
||||
params.imageOffset.x = int32_t(m_CallbackInfo.x);
|
||||
params.imageOffset.y = int32_t(m_CallbackInfo.y);
|
||||
params.imageOffset.z = 0;
|
||||
params.dstBuffer = m_CallbackInfo.dstBuffer;
|
||||
params.depthCopy = true;
|
||||
params.stencilOnly = true;
|
||||
params.mipLevel = m_CallbackInfo.targetSubresource.mip;
|
||||
params.slice = m_CallbackInfo.targetSubresource.slice;
|
||||
// Copy stencil value that indicates the number of fragments ignoring
|
||||
// shader discard.
|
||||
m_pDriver->GetDebugManager()->PixelHistoryCopyPixel(
|
||||
cmd, params, storeOffset + offsetof(struct EventInfo, dsWithoutShaderDiscard));
|
||||
CopyImagePixel(cmd, params, storeOffset + offsetof(struct EventInfo, dsWithoutShaderDiscard));
|
||||
|
||||
// Replay the draw with the original fragment shader to get the actual number
|
||||
// of fragments, accounting for potential shader discard.
|
||||
pipestate.graphics.pipeline = GetResID(replacements.originalShaderStencil);
|
||||
ReplayDraw(cmd, eid, true);
|
||||
|
||||
m_pDriver->GetDebugManager()->PixelHistoryCopyPixel(
|
||||
cmd, params, storeOffset + offsetof(struct EventInfo, dsWithShaderDiscard));
|
||||
CopyImagePixel(cmd, params, storeOffset + offsetof(struct EventInfo, dsWithShaderDiscard));
|
||||
}
|
||||
|
||||
// Restore the state.
|
||||
@@ -1150,19 +1259,12 @@ private:
|
||||
VkCommandBuffer cmd, size_t offset)
|
||||
{
|
||||
CopyPixelParams colourCopyParams = {};
|
||||
colourCopyParams.multisampled = false; // TODO: multisampled
|
||||
colourCopyParams.srcImage = srcImage;
|
||||
colourCopyParams.srcImageLayout =
|
||||
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; // TODO: image layout
|
||||
colourCopyParams.srcImageFormat = srcFormat;
|
||||
colourCopyParams.imageOffset.x = int32_t(m_CallbackInfo.x);
|
||||
colourCopyParams.imageOffset.y = int32_t(m_CallbackInfo.y);
|
||||
colourCopyParams.imageOffset.z = 0;
|
||||
colourCopyParams.dstBuffer = m_CallbackInfo.dstBuffer;
|
||||
colourCopyParams.slice = m_CallbackInfo.targetSubresource.slice;
|
||||
colourCopyParams.mipLevel = m_CallbackInfo.targetSubresource.mip;
|
||||
|
||||
m_pDriver->GetDebugManager()->PixelHistoryCopyPixel(cmd, colourCopyParams, offset);
|
||||
colourCopyParams.srcImageLayout = m_pDriver->GetDebugManager()->GetImageLayout(
|
||||
GetResID(srcImage), VK_IMAGE_ASPECT_COLOR_BIT, m_CallbackInfo.targetSubresource.mip,
|
||||
m_CallbackInfo.targetSubresource.slice);
|
||||
CopyImagePixel(cmd, colourCopyParams, offset);
|
||||
|
||||
if(depthImage != VK_NULL_HANDLE)
|
||||
{
|
||||
@@ -1171,8 +1273,7 @@ private:
|
||||
depthCopyParams.srcImage = depthImage;
|
||||
depthCopyParams.srcImageLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
|
||||
depthCopyParams.srcImageFormat = depthFormat;
|
||||
m_pDriver->GetDebugManager()->PixelHistoryCopyPixel(
|
||||
cmd, depthCopyParams, offset + offsetof(struct PixelHistoryValue, depth));
|
||||
CopyImagePixel(cmd, depthCopyParams, offset + offsetof(struct PixelHistoryValue, depth));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1830,17 +1931,10 @@ struct VulkanPixelHistoryPerFragmentCallback : VulkanPixelHistoryCallback
|
||||
pipesIter[1] = pipes.shaderOutPipe;
|
||||
|
||||
CopyPixelParams colourCopyParams = {};
|
||||
colourCopyParams.multisampled = false; // TODO: multisampled
|
||||
colourCopyParams.srcImage = m_CallbackInfo.subImage;
|
||||
colourCopyParams.srcImageLayout =
|
||||
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; // TODO: image layout
|
||||
colourCopyParams.srcImageFormat = VK_FORMAT_R32G32B32A32_SFLOAT;
|
||||
colourCopyParams.imageOffset.x = int32_t(m_CallbackInfo.x);
|
||||
colourCopyParams.imageOffset.y = int32_t(m_CallbackInfo.y);
|
||||
colourCopyParams.imageOffset.z = 0;
|
||||
colourCopyParams.dstBuffer = m_CallbackInfo.dstBuffer;
|
||||
colourCopyParams.slice = m_CallbackInfo.targetSubresource.slice;
|
||||
colourCopyParams.mipLevel = m_CallbackInfo.targetSubresource.mip;
|
||||
|
||||
const VulkanCreationInfo::Pipeline &p =
|
||||
m_pDriver->GetDebugManager()->GetPipelineInfo(prevState.graphics.pipeline);
|
||||
@@ -1916,11 +2010,11 @@ struct VulkanPixelHistoryPerFragmentCallback : VulkanPixelHistoryCallback
|
||||
depthCopyParams.srcImage = m_CallbackInfo.stencilImage;
|
||||
depthCopyParams.srcImageLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
|
||||
depthCopyParams.srcImageFormat = VK_FORMAT_D32_SFLOAT_S8_UINT;
|
||||
m_pDriver->GetDebugManager()->PixelHistoryCopyPixel(
|
||||
cmd, depthCopyParams, storeOffset + offsetof(struct PixelHistoryValue, depth));
|
||||
CopyImagePixel(cmd, depthCopyParams,
|
||||
storeOffset + offsetof(struct PixelHistoryValue, depth));
|
||||
}
|
||||
}
|
||||
m_pDriver->GetDebugManager()->PixelHistoryCopyPixel(cmd, colourCopyParams, storeOffset);
|
||||
CopyImagePixel(cmd, colourCopyParams, storeOffset);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1971,9 +2065,8 @@ struct VulkanPixelHistoryPerFragmentCallback : VulkanPixelHistoryCallback
|
||||
drawcall->vertexOffset, drawcall->instanceOffset);
|
||||
state.EndRenderPass(cmd);
|
||||
|
||||
m_pDriver->GetDebugManager()->PixelHistoryCopyPixel(
|
||||
cmd, colourCopyParams, (fragsProcessed + f) * sizeof(PerFragmentInfo) +
|
||||
offsetof(struct PerFragmentInfo, postMod));
|
||||
CopyImagePixel(cmd, colourCopyParams, (fragsProcessed + f) * sizeof(PerFragmentInfo) +
|
||||
offsetof(struct PerFragmentInfo, postMod));
|
||||
|
||||
if(depthImage != VK_NULL_HANDLE)
|
||||
{
|
||||
@@ -1982,10 +2075,9 @@ struct VulkanPixelHistoryPerFragmentCallback : VulkanPixelHistoryCallback
|
||||
depthCopyParams.srcImage = depthImage;
|
||||
depthCopyParams.srcImageLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
|
||||
depthCopyParams.srcImageFormat = depthFormat;
|
||||
m_pDriver->GetDebugManager()->PixelHistoryCopyPixel(
|
||||
cmd, depthCopyParams, (fragsProcessed + f) * sizeof(PerFragmentInfo) +
|
||||
offsetof(struct PerFragmentInfo, postMod) +
|
||||
offsetof(struct PixelHistoryValue, depth));
|
||||
CopyImagePixel(cmd, depthCopyParams, (fragsProcessed + f) * sizeof(PerFragmentInfo) +
|
||||
offsetof(struct PerFragmentInfo, postMod) +
|
||||
offsetof(struct PixelHistoryValue, depth));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2342,13 +2434,23 @@ private:
|
||||
};
|
||||
|
||||
bool VulkanDebugManager::PixelHistorySetupResources(PixelHistoryResources &resources,
|
||||
VkExtent3D extent, VkFormat format,
|
||||
uint32_t numEvents)
|
||||
VkImage targetImage, VkExtent3D extent,
|
||||
VkFormat format, VkSampleCountFlagBits samples,
|
||||
const Subresource &sub, uint32_t numEvents)
|
||||
{
|
||||
VkImage colorImage;
|
||||
VkImageView colorImageView;
|
||||
VkImage stencilImage;
|
||||
VkImageView stencilImageView;
|
||||
|
||||
VkImage stagingImage = VK_NULL_HANDLE;
|
||||
VkImageView stagingImageView = VK_NULL_HANDLE;
|
||||
VkDeviceSize stagingImageOffset = 0;
|
||||
VkImage stencilStagingImage = VK_NULL_HANDLE;
|
||||
VkImageView stencilStagingImageView = VK_NULL_HANDLE;
|
||||
VkDeviceSize stencilStagingImageOffset = 0;
|
||||
VkImageView targetImageView = VK_NULL_HANDLE;
|
||||
|
||||
VkDeviceMemory gpuMem;
|
||||
|
||||
VkBuffer dstBuffer;
|
||||
@@ -2357,12 +2459,14 @@ bool VulkanDebugManager::PixelHistorySetupResources(PixelHistoryResources &resou
|
||||
VkResult vkr;
|
||||
VkDevice dev = m_pDriver->GetDev();
|
||||
|
||||
VkDeviceSize totalMemorySize = 0;
|
||||
|
||||
// Create Images
|
||||
VkImageCreateInfo imgInfo = {VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO};
|
||||
imgInfo.imageType = VK_IMAGE_TYPE_2D;
|
||||
imgInfo.mipLevels = 1;
|
||||
imgInfo.arrayLayers = 1;
|
||||
imgInfo.samples = VK_SAMPLE_COUNT_1_BIT;
|
||||
imgInfo.samples = samples;
|
||||
imgInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||
imgInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
|
||||
@@ -2377,29 +2481,53 @@ bool VulkanDebugManager::PixelHistorySetupResources(PixelHistoryResources &resou
|
||||
vkr = m_pDriver->vkCreateImage(dev, &imgInfo, NULL, &colorImage);
|
||||
RDCASSERTEQUAL(vkr, VK_SUCCESS);
|
||||
|
||||
VkImage wrappedColorImage = colorImage;
|
||||
ImageState colorImageState = ImageState(wrappedColorImage, ImageInfo(imgInfo), eFrameRef_None);
|
||||
ImageState colorImageState = ImageState(colorImage, ImageInfo(imgInfo), eFrameRef_None);
|
||||
|
||||
VkMemoryRequirements colorImageMrq = {0};
|
||||
m_pDriver->vkGetImageMemoryRequirements(dev, colorImage, &colorImageMrq);
|
||||
totalMemorySize = colorImageMrq.size;
|
||||
|
||||
imgInfo.format = VK_FORMAT_D32_SFLOAT_S8_UINT;
|
||||
imgInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
|
||||
imgInfo.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT |
|
||||
VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
|
||||
|
||||
vkr = m_pDriver->vkCreateImage(dev, &imgInfo, NULL, &stencilImage);
|
||||
RDCASSERTEQUAL(vkr, VK_SUCCESS);
|
||||
|
||||
VkImage wrappedStencilImage = stencilImage;
|
||||
ImageState stencilImageState = ImageState(wrappedStencilImage, ImageInfo(imgInfo), eFrameRef_None);
|
||||
ImageState stencilImageState = ImageState(stencilImage, ImageInfo(imgInfo), eFrameRef_None);
|
||||
|
||||
VkMemoryRequirements stencilImageMrq = {0};
|
||||
m_pDriver->vkGetImageMemoryRequirements(dev, stencilImage, &stencilImageMrq);
|
||||
VkDeviceSize offset = AlignUp(colorImageMrq.size, stencilImageMrq.alignment);
|
||||
VkDeviceSize offset = AlignUp(totalMemorySize, stencilImageMrq.alignment);
|
||||
totalMemorySize = offset + stencilImageMrq.size;
|
||||
|
||||
if(samples != VK_SAMPLE_COUNT_1_BIT)
|
||||
{
|
||||
imgInfo.format = format;
|
||||
imgInfo.arrayLayers = 1;
|
||||
imgInfo.samples = VK_SAMPLE_COUNT_1_BIT;
|
||||
imgInfo.usage = VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
|
||||
vkr = m_pDriver->vkCreateImage(dev, &imgInfo, NULL, &stagingImage);
|
||||
RDCASSERTEQUAL(vkr, VK_SUCCESS);
|
||||
|
||||
VkMemoryRequirements msImageMrq = {0};
|
||||
m_pDriver->vkGetImageMemoryRequirements(dev, stagingImage, &msImageMrq);
|
||||
stagingImageOffset = AlignUp(totalMemorySize, msImageMrq.alignment);
|
||||
totalMemorySize = stagingImageOffset + msImageMrq.size;
|
||||
|
||||
imgInfo.format = VK_FORMAT_D32_SFLOAT_S8_UINT;
|
||||
imgInfo.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
|
||||
vkr = m_pDriver->vkCreateImage(dev, &imgInfo, NULL, &stencilStagingImage);
|
||||
RDCASSERTEQUAL(vkr, VK_SUCCESS);
|
||||
|
||||
VkMemoryRequirements stencilStagingImageMrq = {0};
|
||||
m_pDriver->vkGetImageMemoryRequirements(dev, stencilStagingImage, &stencilStagingImageMrq);
|
||||
stencilStagingImageOffset = AlignUp(totalMemorySize, stencilStagingImageMrq.alignment);
|
||||
totalMemorySize = stencilStagingImageOffset + stencilStagingImageMrq.size;
|
||||
}
|
||||
|
||||
VkMemoryAllocateInfo allocInfo = {
|
||||
VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, NULL, offset + stencilImageMrq.size,
|
||||
VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, NULL, totalMemorySize,
|
||||
m_pDriver->GetGPULocalMemoryIndex(colorImageMrq.memoryTypeBits),
|
||||
};
|
||||
vkr = m_pDriver->vkAllocateMemory(m_Device, &allocInfo, NULL, &gpuMem);
|
||||
@@ -2427,6 +2555,55 @@ bool VulkanDebugManager::PixelHistorySetupResources(PixelHistoryResources &resou
|
||||
vkr = m_pDriver->vkCreateImageView(m_Device, &viewInfo, NULL, &stencilImageView);
|
||||
RDCASSERTEQUAL(vkr, VK_SUCCESS);
|
||||
|
||||
if(samples != VK_SAMPLE_COUNT_1_BIT)
|
||||
{
|
||||
vkr = m_pDriver->vkBindImageMemory(m_Device, stagingImage, gpuMem, stagingImageOffset);
|
||||
RDCASSERTEQUAL(vkr, VK_SUCCESS);
|
||||
|
||||
viewInfo.image = stagingImage;
|
||||
viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
|
||||
viewInfo.subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, VK_REMAINING_MIP_LEVELS, 0,
|
||||
VK_REMAINING_ARRAY_LAYERS};
|
||||
|
||||
uint32_t bs = GetByteSize(1, 1, 1, format, 0);
|
||||
|
||||
if(bs == 1)
|
||||
viewInfo.format = VK_FORMAT_R8_UINT;
|
||||
else if(bs == 2)
|
||||
viewInfo.format = VK_FORMAT_R16_UINT;
|
||||
else if(bs == 4)
|
||||
viewInfo.format = VK_FORMAT_R32_UINT;
|
||||
else if(bs == 8)
|
||||
viewInfo.format = VK_FORMAT_R32G32_UINT;
|
||||
else if(bs == 16)
|
||||
viewInfo.format = VK_FORMAT_R32G32B32A32_UINT;
|
||||
|
||||
if(viewInfo.format == VK_FORMAT_UNDEFINED)
|
||||
{
|
||||
RDCERR("Can't copy 2D to Array with format %s", ToStr(format).c_str());
|
||||
}
|
||||
|
||||
vkr = m_pDriver->vkCreateImageView(m_Device, &viewInfo, NULL, &stagingImageView);
|
||||
RDCASSERTEQUAL(vkr, VK_SUCCESS);
|
||||
|
||||
viewInfo.image = targetImage;
|
||||
viewInfo.subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, sub.mip, 1, sub.slice, 1};
|
||||
vkr = m_pDriver->vkCreateImageView(m_Device, &viewInfo, NULL, &targetImageView);
|
||||
RDCASSERTEQUAL(vkr, VK_SUCCESS);
|
||||
|
||||
viewInfo.image = stencilStagingImage;
|
||||
viewInfo.format = VK_FORMAT_D32_SFLOAT_S8_UINT;
|
||||
viewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
|
||||
viewInfo.subresourceRange.baseArrayLayer = 0;
|
||||
|
||||
vkr = m_pDriver->vkBindImageMemory(m_Device, stencilStagingImage, gpuMem,
|
||||
stencilStagingImageOffset);
|
||||
RDCASSERTEQUAL(vkr, VK_SUCCESS);
|
||||
|
||||
vkr = m_pDriver->vkCreateImageView(m_Device, &viewInfo, NULL, &stencilStagingImageView);
|
||||
RDCASSERTEQUAL(vkr, VK_SUCCESS);
|
||||
}
|
||||
|
||||
VkBufferCreateInfo bufferInfo = {VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO};
|
||||
bufferInfo.size = AlignUp((uint32_t)(numEvents * sizeof(EventInfo)), 4096U);
|
||||
bufferInfo.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT;
|
||||
@@ -2468,6 +2645,11 @@ bool VulkanDebugManager::PixelHistorySetupResources(PixelHistoryResources &resou
|
||||
resources.colorImageView = colorImageView;
|
||||
resources.stencilImage = stencilImage;
|
||||
resources.stencilImageView = stencilImageView;
|
||||
resources.stagingImage = stagingImage;
|
||||
resources.stagingImageView = stagingImageView;
|
||||
resources.stencilStagingImage = stencilStagingImage;
|
||||
resources.stencilStagingImageView = stencilStagingImageView;
|
||||
resources.targetImageView = targetImageView;
|
||||
resources.gpuMem = gpuMem;
|
||||
|
||||
resources.bufferMemory = bufferMemory;
|
||||
@@ -2476,6 +2658,28 @@ bool VulkanDebugManager::PixelHistorySetupResources(PixelHistoryResources &resou
|
||||
return true;
|
||||
}
|
||||
|
||||
void VulkanReplay::UpdatePixelHistoryDescriptor(VkImageView sourceView, VkImageView destView)
|
||||
{
|
||||
VkDescriptorImageInfo srcdesc = {0};
|
||||
srcdesc.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
||||
srcdesc.imageView = Unwrap(sourceView);
|
||||
srcdesc.sampler = Unwrap(m_General.PointSampler); // not used - we use texelFetch
|
||||
|
||||
VkDescriptorImageInfo destdesc = {0};
|
||||
destdesc.imageLayout = VK_IMAGE_LAYOUT_GENERAL;
|
||||
destdesc.imageView = Unwrap(destView);
|
||||
|
||||
VkWriteDescriptorSet writeSet[] = {
|
||||
{VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, NULL, Unwrap(m_PixelHistory.MSCopyDescSet), 0, 0, 1,
|
||||
VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &srcdesc, NULL, NULL},
|
||||
{VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, NULL, Unwrap(m_PixelHistory.MSCopyDescSet), 2, 0, 1,
|
||||
VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &destdesc, NULL, NULL},
|
||||
};
|
||||
|
||||
ObjDisp(m_pDriver->GetDev())
|
||||
->UpdateDescriptorSets(Unwrap(m_pDriver->GetDev()), ARRAY_COUNT(writeSet), writeSet, 0, NULL);
|
||||
}
|
||||
|
||||
bool VulkanDebugManager::PixelHistoryDestroyResources(const PixelHistoryResources &r)
|
||||
{
|
||||
VkDevice dev = m_pDriver->GetDev();
|
||||
@@ -2489,6 +2693,14 @@ bool VulkanDebugManager::PixelHistoryDestroyResources(const PixelHistoryResource
|
||||
m_pDriver->vkDestroyImage(dev, r.stencilImage, NULL);
|
||||
if(r.stencilImageView != VK_NULL_HANDLE)
|
||||
m_pDriver->vkDestroyImageView(dev, r.stencilImageView, NULL);
|
||||
if(r.stagingImage != VK_NULL_HANDLE)
|
||||
m_pDriver->vkDestroyImage(dev, r.stagingImage, NULL);
|
||||
if(r.stagingImageView != VK_NULL_HANDLE)
|
||||
m_pDriver->vkDestroyImageView(dev, r.stagingImageView, NULL);
|
||||
if(r.stencilStagingImage != VK_NULL_HANDLE)
|
||||
m_pDriver->vkDestroyImage(dev, r.stencilStagingImage, NULL);
|
||||
if(r.stencilStagingImageView != VK_NULL_HANDLE)
|
||||
m_pDriver->vkDestroyImageView(dev, r.stencilStagingImageView, NULL);
|
||||
if(r.dstBuffer != VK_NULL_HANDLE)
|
||||
m_pDriver->vkDestroyBuffer(dev, r.dstBuffer, NULL);
|
||||
if(r.bufferMemory != VK_NULL_HANDLE)
|
||||
@@ -2496,79 +2708,6 @@ bool VulkanDebugManager::PixelHistoryDestroyResources(const PixelHistoryResource
|
||||
return true;
|
||||
}
|
||||
|
||||
void VulkanDebugManager::PixelHistoryCopyPixel(VkCommandBuffer cmd, CopyPixelParams &p, size_t offset)
|
||||
{
|
||||
rdcarray<VkBufferImageCopy> regions;
|
||||
// Check if depth image includes depth and stencil
|
||||
VkImageAspectFlags aspectFlags = 0;
|
||||
VkBufferImageCopy region = {};
|
||||
region.bufferOffset = (uint64_t)offset;
|
||||
region.bufferRowLength = 0;
|
||||
region.bufferImageHeight = 0;
|
||||
region.imageOffset = p.imageOffset;
|
||||
region.imageExtent.width = 1U;
|
||||
region.imageExtent.height = 1U;
|
||||
region.imageExtent.depth = 1U;
|
||||
|
||||
if(!p.depthCopy)
|
||||
{
|
||||
region.imageSubresource =
|
||||
VkImageSubresourceLayers{VK_IMAGE_ASPECT_COLOR_BIT, p.mipLevel, p.slice, 1};
|
||||
regions.push_back(region);
|
||||
aspectFlags = VkImageAspectFlags(VK_IMAGE_ASPECT_COLOR_BIT);
|
||||
}
|
||||
else if(p.stencilOnly)
|
||||
{
|
||||
region.imageSubresource =
|
||||
VkImageSubresourceLayers{VK_IMAGE_ASPECT_STENCIL_BIT, p.mipLevel, p.slice, 1};
|
||||
aspectFlags = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
|
||||
regions.push_back(region);
|
||||
}
|
||||
else
|
||||
{
|
||||
region.imageSubresource =
|
||||
VkImageSubresourceLayers{VK_IMAGE_ASPECT_DEPTH_BIT, p.mipLevel, p.slice, 1};
|
||||
if(IsDepthOnlyFormat(p.srcImageFormat) || IsDepthAndStencilFormat(p.srcImageFormat))
|
||||
{
|
||||
regions.push_back(region);
|
||||
aspectFlags |= VK_IMAGE_ASPECT_DEPTH_BIT;
|
||||
}
|
||||
if(IsStencilFormat(p.srcImageFormat))
|
||||
{
|
||||
region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT;
|
||||
region.bufferOffset = offset + 4;
|
||||
regions.push_back(region);
|
||||
aspectFlags |= VK_IMAGE_ASPECT_STENCIL_BIT;
|
||||
}
|
||||
}
|
||||
|
||||
VkImageMemoryBarrier barrier = {VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
|
||||
NULL,
|
||||
VK_ACCESS_SHADER_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
|
||||
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT |
|
||||
VK_ACCESS_TRANSFER_WRITE_BIT | VK_ACCESS_MEMORY_WRITE_BIT,
|
||||
VK_ACCESS_TRANSFER_READ_BIT,
|
||||
p.srcImageLayout,
|
||||
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
|
||||
VK_QUEUE_FAMILY_IGNORED,
|
||||
VK_QUEUE_FAMILY_IGNORED,
|
||||
Unwrap(p.srcImage),
|
||||
{aspectFlags, 0, 1, 0, 1}};
|
||||
|
||||
DoPipelineBarrier(cmd, 1, &barrier);
|
||||
|
||||
ObjDisp(cmd)->CmdCopyImageToBuffer(Unwrap(cmd), Unwrap(p.srcImage),
|
||||
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, Unwrap(p.dstBuffer),
|
||||
(uint32_t)regions.size(), regions.data());
|
||||
|
||||
barrier.image = Unwrap(p.srcImage);
|
||||
barrier.srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
|
||||
barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
|
||||
barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
|
||||
barrier.newLayout = p.srcImageLayout;
|
||||
DoPipelineBarrier(cmd, 1, &barrier);
|
||||
}
|
||||
|
||||
void CreateOcclusionPool(WrappedVulkan *vk, uint32_t poolSize, VkQueryPool *pQueryPool)
|
||||
{
|
||||
VkDevice dev = vk->GetDev();
|
||||
@@ -2708,15 +2847,8 @@ rdcarray<PixelModification> VulkanReplay::PixelHistory(rdcarray<EventUsage> even
|
||||
if(imginfo.format == VK_FORMAT_UNDEFINED)
|
||||
return history;
|
||||
|
||||
uint32_t mip = sub.mip;
|
||||
uint32_t slice = sub.slice;
|
||||
uint32_t sampleIdx = sub.sample;
|
||||
|
||||
// TODO: figure out correct aspect.
|
||||
VkImageLayout imgLayout =
|
||||
GetDebugManager()->GetImageLayout(target, VK_IMAGE_ASPECT_COLOR_BIT, mip, slice);
|
||||
RDCASSERTNOTEQUAL(imgLayout, VK_IMAGE_LAYOUT_UNDEFINED);
|
||||
|
||||
// TODO: use the given type hint for typeless textures
|
||||
SCOPED_TIMER("VkDebugManager::PixelHistory");
|
||||
|
||||
@@ -2737,17 +2869,24 @@ rdcarray<PixelModification> VulkanReplay::PixelHistory(rdcarray<EventUsage> even
|
||||
CreateOcclusionPool(m_pDriver, (uint32_t)events.size(), &occlusionPool);
|
||||
|
||||
PixelHistoryResources resources = {};
|
||||
GetDebugManager()->PixelHistorySetupResources(resources, imginfo.extent, imginfo.format,
|
||||
// TODO: perhaps should do this after making an occlusion query, since we will
|
||||
// get a smaller subset of events that passed the occlusion query.
|
||||
VkImage targetImage = GetResourceManager()->GetCurrentHandle<VkImage>(target);
|
||||
GetDebugManager()->PixelHistorySetupResources(resources, targetImage, imginfo.extent,
|
||||
imginfo.format, imginfo.samples, sub,
|
||||
(uint32_t)events.size());
|
||||
if(multisampled)
|
||||
UpdatePixelHistoryDescriptor(resources.targetImageView, resources.stagingImageView);
|
||||
|
||||
PixelHistoryShaderCache *shaderCache = new PixelHistoryShaderCache(m_pDriver);
|
||||
VkImage targetImage = GetResourceManager()->GetCurrentHandle<VkImage>(target);
|
||||
|
||||
PixelHistoryCallbackInfo callbackInfo = {};
|
||||
callbackInfo.targetImage = targetImage;
|
||||
callbackInfo.targetImageFormat = imginfo.format;
|
||||
callbackInfo.layers = imginfo.arrayLayers;
|
||||
callbackInfo.mipLevels = imginfo.mipLevels;
|
||||
callbackInfo.samples = imginfo.samples;
|
||||
callbackInfo.extent = imginfo.extent;
|
||||
callbackInfo.targetSubresource = sub;
|
||||
callbackInfo.x = x;
|
||||
callbackInfo.y = y;
|
||||
@@ -2757,6 +2896,8 @@ rdcarray<PixelModification> VulkanReplay::PixelHistory(rdcarray<EventUsage> even
|
||||
callbackInfo.stencilImage = resources.stencilImage;
|
||||
callbackInfo.stencilImageView = resources.stencilImageView;
|
||||
callbackInfo.dstBuffer = resources.dstBuffer;
|
||||
callbackInfo.stagingImage = resources.stagingImage;
|
||||
callbackInfo.stencilStagingImage = resources.stencilStagingImage;
|
||||
|
||||
VulkanOcclusionCallback occlCb(m_pDriver, shaderCache, callbackInfo, occlusionPool, events);
|
||||
m_pDriver->ReplayLog(0, events.back().eventId, eReplay_Full);
|
||||
|
||||
@@ -2795,6 +2795,13 @@ rdcarray<EventUsage> VulkanReplay::GetUsage(ResourceId id)
|
||||
return m_pDriver->GetUsage(id);
|
||||
}
|
||||
|
||||
void VulkanReplay::CopyPixelForPixelHistory(VkCommandBuffer cmd, VkExtent3D extent, uint32_t sample,
|
||||
VkFormat fmt)
|
||||
{
|
||||
m_pDriver->GetDebugManager()->CopyTex2DMSPixel(cmd, m_PixelHistory.MSCopyDescSet, extent, sample,
|
||||
fmt);
|
||||
}
|
||||
|
||||
void VulkanReplay::GetTextureData(ResourceId tex, const Subresource &sub,
|
||||
const GetTextureDataParams ¶ms, bytebuf &data)
|
||||
{
|
||||
|
||||
@@ -319,6 +319,7 @@ public:
|
||||
float *maxval);
|
||||
bool GetHistogram(ResourceId texid, const Subresource &sub, CompType typeCast, float minval,
|
||||
float maxval, bool channels[4], rdcarray<uint32_t> &histogram);
|
||||
void UpdatePixelHistoryDescriptor(VkImageView sourceView, VkImageView destView);
|
||||
|
||||
void InitPostVSBuffers(uint32_t eventId);
|
||||
void InitPostVSBuffers(uint32_t eventId, VulkanRenderState &state);
|
||||
@@ -410,6 +411,9 @@ public:
|
||||
void SetDriverInformation(const VkPhysicalDeviceProperties &props);
|
||||
|
||||
AMDCounters *GetAMDCounters() { return m_pAMDCounters; }
|
||||
void CopyPixelForPixelHistory(VkCommandBuffer cmd, VkExtent3D extent, uint32_t sample,
|
||||
VkFormat fmt);
|
||||
|
||||
private:
|
||||
void FetchShaderFeedback(uint32_t eventId);
|
||||
void ClearFeedbackCache();
|
||||
@@ -653,6 +657,15 @@ private:
|
||||
VkRenderPass RP = VK_NULL_HANDLE;
|
||||
} m_PixelPick;
|
||||
|
||||
struct PixelHistory
|
||||
{
|
||||
void Init(WrappedVulkan *driver, VkDescriptorPool descriptorPool);
|
||||
void Destroy(WrappedVulkan *driver);
|
||||
|
||||
VkDescriptorSetLayout MSCopyDescSetLayout = VK_NULL_HANDLE;
|
||||
VkDescriptorSet MSCopyDescSet = VK_NULL_HANDLE;
|
||||
} m_PixelHistory;
|
||||
|
||||
struct HistogramMinMax
|
||||
{
|
||||
void Init(WrappedVulkan *driver, VkDescriptorPool descriptorPool);
|
||||
|
||||
@@ -74,18 +74,32 @@ void main()
|
||||
|
||||
)EOSHADER";
|
||||
|
||||
std::string whitepixel = R"EOSHADER(
|
||||
std::string mspixel = R"EOSHADER(
|
||||
#version 420 core
|
||||
|
||||
layout(location = 0, index = 0) out vec4 Color;
|
||||
|
||||
void main()
|
||||
{
|
||||
Color = vec4(1,1,1,1);
|
||||
if (gl_SampleID == 0)
|
||||
Color = vec4(1, 0, 0, 1);
|
||||
else if (gl_SampleID == 1)
|
||||
Color = vec4(0, 0, 1, 1);
|
||||
else if (gl_SampleID == 2)
|
||||
Color = vec4(0, 1, 1, 1);
|
||||
else if (gl_SampleID == 3)
|
||||
Color = vec4(1, 1, 1, 1);
|
||||
}
|
||||
|
||||
)EOSHADER";
|
||||
|
||||
void Prepare(int argc, char **argv)
|
||||
{
|
||||
features.sampleRateShading = true;
|
||||
|
||||
VulkanGraphicsTest::Prepare(argc, argv);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
optDevExts.push_back(VK_KHR_MAINTENANCE1_EXTENSION_NAME);
|
||||
@@ -287,6 +301,30 @@ void main()
|
||||
subrp, {subview},
|
||||
{mainWindow->scissor.extent.width / 4, mainWindow->scissor.extent.height / 4}));
|
||||
|
||||
renderPassCreateInfo.attachments[0].samples = VK_SAMPLE_COUNT_4_BIT;
|
||||
|
||||
VkRenderPass submsrp = createRenderPass(renderPassCreateInfo);
|
||||
|
||||
pipeCreateInfo.stages[1] =
|
||||
CompileShaderModule(mspixel, ShaderLang::glsl, ShaderStage::frag, "main");
|
||||
|
||||
pipeCreateInfo.renderPass = submsrp;
|
||||
pipeCreateInfo.multisampleState.rasterizationSamples = VK_SAMPLE_COUNT_4_BIT;
|
||||
VkPipeline mspipe = createGraphicsPipeline(pipeCreateInfo);
|
||||
|
||||
AllocatedImage submsimg(
|
||||
this, vkh::ImageCreateInfo(mainWindow->scissor.extent.width,
|
||||
mainWindow->scissor.extent.height, 0, mainWindow->format,
|
||||
VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, 1, 4, VK_SAMPLE_COUNT_4_BIT),
|
||||
VmaAllocationCreateInfo({0, VMA_MEMORY_USAGE_GPU_ONLY}));
|
||||
|
||||
VkImageView submsview = createImageView(vkh::ImageViewCreateInfo(
|
||||
submsimg.image, VK_IMAGE_VIEW_TYPE_2D, mainWindow->format, {},
|
||||
vkh::ImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 2, 1)));
|
||||
|
||||
VkFramebuffer submsfb = createFramebuffer(vkh::FramebufferCreateInfo(
|
||||
submsrp, {submsview}, {mainWindow->scissor.extent.width, mainWindow->scissor.extent.height}));
|
||||
|
||||
while(Running())
|
||||
{
|
||||
VkCommandBuffer cmd = GetCommandBuffer();
|
||||
@@ -349,6 +387,20 @@ void main()
|
||||
|
||||
vkCmdEndRenderPass(cmd);
|
||||
|
||||
{
|
||||
setMarker(cmd, "Multisampled: begin renderpass");
|
||||
vkCmdBeginRenderPass(cmd, vkh::RenderPassBeginInfo(submsrp, submsfb, mainWindow->scissor,
|
||||
{vkh::ClearValue(0.f, 1.0f, 0.f, 1.0f)}),
|
||||
VK_SUBPASS_CONTENTS_INLINE);
|
||||
|
||||
vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, mspipe);
|
||||
|
||||
setMarker(cmd, "Multisampled: test");
|
||||
vkCmdDraw(cmd, 6, 1, 3, 0);
|
||||
|
||||
vkCmdEndRenderPass(cmd);
|
||||
}
|
||||
|
||||
v = mainWindow->viewport;
|
||||
v.width /= 4.0f;
|
||||
v.height /= 4.0f;
|
||||
@@ -403,7 +455,6 @@ void main()
|
||||
FinishUsingBackbuffer(cmd, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_GENERAL);
|
||||
|
||||
vkEndCommandBuffer(cmd);
|
||||
|
||||
Submit(0, 1, {cmd});
|
||||
|
||||
Present();
|
||||
|
||||
@@ -26,6 +26,7 @@ class VK_Pixel_History(rdtest.TestCase):
|
||||
return
|
||||
|
||||
self.primary_test()
|
||||
self.multisampled_image_test()
|
||||
self.secondary_cmd_test()
|
||||
|
||||
def primary_test(self):
|
||||
@@ -101,6 +102,42 @@ class VK_Pixel_History(rdtest.TestCase):
|
||||
self.check_events(events, modifs, False)
|
||||
self.check_pixel_value(tex, x, y, value_selector(modifs[-1].postMod.col), sub=sub, cast=rt.typeCast)
|
||||
|
||||
def multisampled_image_test(self):
|
||||
test_marker: rd.DrawcallDescription = self.find_draw("Multisampled: test")
|
||||
draw_eid = test_marker.next.eventId
|
||||
self.controller.SetFrameEvent(draw_eid, True)
|
||||
|
||||
pipe: rd.PipeState = self.controller.GetPipelineState()
|
||||
rt: rd.BoundResource = pipe.GetOutputTargets()[0]
|
||||
sub = rd.Subresource()
|
||||
tex = rt.resourceId
|
||||
tex_details = self.get_texture(tex)
|
||||
if tex_details.arraysize > 1:
|
||||
sub.slice = rt.firstSlice
|
||||
|
||||
beg_renderpass_eid = self.find_draw("Multisampled: begin renderpass").next.eventId
|
||||
|
||||
x, y = 100, 200
|
||||
sub.sample = 1
|
||||
rdtest.log.print("Testing pixel {}, {} at sample {}".format(x, y, sub.sample))
|
||||
modifs: List[rd.PixelModification] = self.controller.PixelHistory(tex, x, y, sub, rt.typeCast)
|
||||
events = [
|
||||
[[event_id, beg_renderpass_eid], [passed, True], [post_mod_col, (0.0, 1.0, 0.0, 1.0)]],
|
||||
[[event_id, draw_eid], [passed, True], [post_mod_col, (0.0, 0.0, 1.0, 1.0)]],
|
||||
]
|
||||
self.check_events(events, modifs, True)
|
||||
self.check_pixel_value(tex, x, y, value_selector(modifs[-1].postMod.col), sub=sub, cast=rt.typeCast)
|
||||
|
||||
sub.sample = 2
|
||||
rdtest.log.print("Testing pixel {}, {} at sample {}".format(x, y, sub.sample))
|
||||
modifs: List[rd.PixelModification] = self.controller.PixelHistory(tex, x, y, sub, rt.typeCast)
|
||||
events = [
|
||||
[[event_id, beg_renderpass_eid], [passed, True], [post_mod_col, (0.0, 1.0, 0.0, 1.0)]],
|
||||
[[event_id, draw_eid], [passed, True], [post_mod_col, (0.0, 1.0, 1.0, 1.0)]],
|
||||
]
|
||||
self.check_events(events, modifs, True)
|
||||
self.check_pixel_value(tex, x, y, value_selector(modifs[-1].postMod.col), sub=sub, cast=rt.typeCast)
|
||||
|
||||
def secondary_cmd_test(self):
|
||||
secondary_marker: rd.DrawcallDescription = self.find_draw("Secondary: red and blue")
|
||||
self.controller.SetFrameEvent(secondary_marker.next.eventId, True)
|
||||
|
||||
Reference in New Issue
Block a user