Implement histogram and min/max fetching via compute

This commit is contained in:
baldurk
2015-12-31 22:39:46 +01:00
parent 7441a3dc1e
commit d5aa1da377
11 changed files with 1023 additions and 72 deletions
+3
View File
@@ -58,5 +58,8 @@ DECLARE_EMBED(fixedcolfs_spv);
DECLARE_EMBED(meshvs_spv);
DECLARE_EMBED(meshgs_spv);
DECLARE_EMBED(meshfs_spv);
DECLARE_EMBED(minmaxtilecs_spv);
DECLARE_EMBED(minmaxresultcs_spv);
DECLARE_EMBED(histogramcs_spv);
#undef DECLARE_EMBED
+3
View File
@@ -142,6 +142,9 @@ RESOURCE_fixedcolfs_spv TYPE_EMBED "spv/fixedcolfs.spv"
RESOURCE_meshvs_spv TYPE_EMBED "spv/meshvs.spv"
RESOURCE_meshgs_spv TYPE_EMBED "spv/meshgs.spv"
RESOURCE_meshfs_spv TYPE_EMBED "spv/meshfs.spv"
RESOURCE_minmaxtilecs_spv TYPE_EMBED "spv/minmaxtilecs.spv"
RESOURCE_minmaxresultcs_spv TYPE_EMBED "spv/minmaxresultcs.spv"
RESOURCE_histogramcs_spv TYPE_EMBED "spv/histogramcs.spv"
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
+70 -67
View File
@@ -1,67 +1,70 @@
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by renderdoc.rc
//
#define TYPE_EMBED 256
#define RESOURCE_debugdisplay_hlsl 101
#define RESOURCE_debugtext_hlsl 102
#define RESOURCE_debugcbuffers_h 103
#define RESOURCE_debugcommon_hlsl 104
#define RESOURCE_histogram_hlsl 105
#define RESOURCE_multisample_hlsl 106
#define RESOURCE_mesh_hlsl 107
#define RESOURCE_blit_vert 201
#define RESOURCE_blit_frag 202
#define RESOURCE_texdisplay_frag 203
#define RESOURCE_checkerboard_frag 204
#define RESOURCE_generic_vert 205
#define RESOURCE_generic_frag 206
#define RESOURCE_mesh_vert 207
#define RESOURCE_debuguniforms_h 208
#define RESOURCE_text_vert 209
#define RESOURCE_text_frag 210
#define RESOURCE_texsample_h 211
#define RESOURCE_histogram_comp 212
#define RESOURCE_mesh_frag 213
#define RESOURCE_mesh_geom 214
#define RESOURCE_mesh_comp 215
#define RESOURCE_arraymscopy_comp 216
#define RESOURCE_quadoverdraw_frag 217
#define RESOURCE_outline_frag 218
#define RESOURCE_sourcecodepro_ttf 301
#define RESOURCE_blitvs_spv 401
#define RESOURCE_checkerboardfs_spv 402
#define RESOURCE_texdisplayfs_spv 403
#define RESOURCE_textvs_spv 404
#define RESOURCE_textfs_spv 405
#define RESOURCE_genericvs_spv 406
#define RESOURCE_genericfs_spv 407
#define RESOURCE_fixedcolfs_spv 408
#define RESOURCE_meshvs_spv 409
#define RESOURCE_meshgs_spv 410
#define RESOURCE_meshfs_spv 411
#if !defined(STRINGIZE)
#define STRINGIZE2(a) #a
#define STRINGIZE(a) STRINGIZE2(a)
#endif
#define GIT_COMMIT_HASH "NO_GIT_COMMIT_HASH_DEFINED"
//#define RENDERDOC_OFFICIAL_BUILD // used to determine whether to submit auto crash reports
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 114
#define _APS_NEXT_COMMAND_VALUE 40029
#define _APS_NEXT_CONTROL_VALUE 1000
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif
#include "version.h"
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by renderdoc.rc
//
#define TYPE_EMBED 256
#define RESOURCE_debugdisplay_hlsl 101
#define RESOURCE_debugtext_hlsl 102
#define RESOURCE_debugcbuffers_h 103
#define RESOURCE_debugcommon_hlsl 104
#define RESOURCE_histogram_hlsl 105
#define RESOURCE_multisample_hlsl 106
#define RESOURCE_mesh_hlsl 107
#define RESOURCE_blit_vert 201
#define RESOURCE_blit_frag 202
#define RESOURCE_texdisplay_frag 203
#define RESOURCE_checkerboard_frag 204
#define RESOURCE_generic_vert 205
#define RESOURCE_generic_frag 206
#define RESOURCE_mesh_vert 207
#define RESOURCE_debuguniforms_h 208
#define RESOURCE_text_vert 209
#define RESOURCE_text_frag 210
#define RESOURCE_texsample_h 211
#define RESOURCE_histogram_comp 212
#define RESOURCE_mesh_frag 213
#define RESOURCE_mesh_geom 214
#define RESOURCE_mesh_comp 215
#define RESOURCE_arraymscopy_comp 216
#define RESOURCE_quadoverdraw_frag 217
#define RESOURCE_outline_frag 218
#define RESOURCE_sourcecodepro_ttf 301
#define RESOURCE_blitvs_spv 401
#define RESOURCE_checkerboardfs_spv 402
#define RESOURCE_texdisplayfs_spv 403
#define RESOURCE_textvs_spv 404
#define RESOURCE_textfs_spv 405
#define RESOURCE_genericvs_spv 406
#define RESOURCE_genericfs_spv 407
#define RESOURCE_fixedcolfs_spv 408
#define RESOURCE_meshvs_spv 409
#define RESOURCE_meshgs_spv 410
#define RESOURCE_meshfs_spv 411
#define RESOURCE_minmaxtilecs_spv 412
#define RESOURCE_minmaxresultcs_spv 413
#define RESOURCE_histogramcs_spv 414
#if !defined(STRINGIZE)
#define STRINGIZE2(a) #a
#define STRINGIZE(a) STRINGIZE2(a)
#endif
#define GIT_COMMIT_HASH "NO_GIT_COMMIT_HASH_DEFINED"
//#define RENDERDOC_OFFICIAL_BUILD // used to determine whether to submit auto crash reports
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 114
#define _APS_NEXT_COMMAND_VALUE 40029
#define _APS_NEXT_CONTROL_VALUE 1000
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif
#include "version.h"
+124
View File
@@ -0,0 +1,124 @@
/******************************************************************************
* The MIT License (MIT)
*
* Copyright (c) 2014 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.
******************************************************************************/
// compute shaders that figure out the min/max values or histogram in a texture heirarchically
// note that we have to conditionally compile this shader for float/uint/sint as doing that
// dynamically produces a shader with too many temp registers unfortunately.
#version 430 core
#define HGRAM_PIXELS_PER_TILE 64u
#define HGRAM_TILES_PER_BLOCK 32u
#define HGRAM_NUM_BUCKETS 256u
layout(binding=0, std140) writeonly buffer minmaxresultdest
{
uint result[HGRAM_NUM_BUCKETS];
} dest;
layout(binding=2, std140) uniform HistogramCBufferData
{
uint HistogramChannels;
float HistogramMin;
float HistogramMax;
uint HistogramFlags;
float HistogramSlice;
int HistogramMip;
int HistogramSample;
int HistogramNumSamples;
vec3 HistogramTextureResolution;
float Padding3;
} histogram;
layout (binding = 3) uniform sampler2D tex;
layout (local_size_x = HGRAM_TILES_PER_BLOCK, local_size_y = HGRAM_TILES_PER_BLOCK) in;
void main()
{
uvec3 tid = gl_LocalInvocationID;
uvec3 gid = gl_WorkGroupID;
uvec3 texDim = uvec3(histogram.HistogramTextureResolution);
uint blocksX = uint(ceil(float(texDim.x)/float(HGRAM_PIXELS_PER_TILE*HGRAM_TILES_PER_BLOCK)));
uvec2 topleft = (gid.xy*HGRAM_TILES_PER_BLOCK + tid.xy)*HGRAM_PIXELS_PER_TILE;
int i=0;
for(uint y=topleft.y; y < min(texDim.y, topleft.y + HGRAM_PIXELS_PER_TILE); y++)
{
for(uint x=topleft.x; x < min(texDim.x, topleft.x + HGRAM_PIXELS_PER_TILE); x++)
{
uint bucketIdx = HGRAM_NUM_BUCKETS+1;
{
vec4 data = textureLod(tex, vec2(x, y) / histogram.HistogramTextureResolution.xy, float(histogram.HistogramMip));
float divisor = 0.0f;
float sum = 0.0f;
if((histogram.HistogramChannels & 0x1u) > 0)
{
sum += data.x;
divisor += 1.0f;
}
if((histogram.HistogramChannels & 0x2u) > 0)
{
sum += data.y;
divisor += 1.0f;
}
if((histogram.HistogramChannels & 0x4u) > 0)
{
sum += data.z;
divisor += 1.0f;
}
if((histogram.HistogramChannels & 0x8u) > 0)
{
sum += data.w;
divisor += 1.0f;
}
if(divisor > 0.0f)
{
float val = sum/divisor;
float normalisedVal = (val - histogram.HistogramMin)/(histogram.HistogramMax - histogram.HistogramMin);
if(normalisedVal < 0.0f)
normalisedVal = 2.0f;
bucketIdx = uint(floor(normalisedVal*HGRAM_NUM_BUCKETS));
}
}
if(bucketIdx >= 0 && bucketIdx < HGRAM_NUM_BUCKETS)
atomicAdd(dest.result[bucketIdx], 1U);
}
}
}
+96
View File
@@ -0,0 +1,96 @@
/******************************************************************************
* The MIT License (MIT)
*
* Copyright (c) 2014 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.
******************************************************************************/
// compute shaders that figure out the min/max values or histogram in a texture heirarchically
// note that we have to conditionally compile this shader for float/uint/sint as doing that
// dynamically produces a shader with too many temp registers unfortunately.
#version 430 core
#define HGRAM_PIXELS_PER_TILE 64u
#define HGRAM_TILES_PER_BLOCK 32u
#define HGRAM_NUM_BUCKETS 256u
layout(binding=0, std140) writeonly buffer minmaxresultdest
{
vec4 result[2];
} dest;
layout(binding=1, std140) readonly buffer minmaxtilesrc
{
vec4 tiles[];
} src;
layout(binding=2, std140) uniform HistogramCBufferData
{
uint HistogramChannels;
float HistogramMin;
float HistogramMax;
uint HistogramFlags;
float HistogramSlice;
int HistogramMip;
int HistogramSample;
int HistogramNumSamples;
vec3 HistogramTextureResolution;
float Padding3;
} minmax;
layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
void main()
{
uvec3 texDim = uvec3(minmax.HistogramTextureResolution);
uint blocksX = uint(ceil(float(texDim.x)/float(HGRAM_PIXELS_PER_TILE*HGRAM_TILES_PER_BLOCK)));
uint blocksY = uint(ceil(float(texDim.y)/float(HGRAM_PIXELS_PER_TILE*HGRAM_TILES_PER_BLOCK)));
vec4 minvalF = src.tiles[0];
vec4 maxvalF = src.tiles[1];
// i is the tile we're looking at
for(uint i=1; i < blocksX*blocksY*HGRAM_TILES_PER_BLOCK*HGRAM_TILES_PER_BLOCK; i++)
{
uint blockIdx = i/(HGRAM_TILES_PER_BLOCK*HGRAM_TILES_PER_BLOCK);
uint tileIdx = i%(HGRAM_TILES_PER_BLOCK*HGRAM_TILES_PER_BLOCK);
// which block and tile is this in
uvec2 blockXY = uvec2(blockIdx % blocksX, blockIdx / blocksX);
uvec2 tileXY = uvec2(tileIdx % HGRAM_TILES_PER_BLOCK, tileIdx / HGRAM_TILES_PER_BLOCK);
// if this is at least partially within the texture, include it.
if(blockXY.x*(HGRAM_TILES_PER_BLOCK*HGRAM_TILES_PER_BLOCK) + tileXY.x*HGRAM_PIXELS_PER_TILE < texDim.x &&
blockXY.y*(HGRAM_TILES_PER_BLOCK*HGRAM_TILES_PER_BLOCK) + tileXY.y*HGRAM_PIXELS_PER_TILE < texDim.y)
{
minvalF = min(minvalF, src.tiles[i*2 + 0]);
maxvalF = max(maxvalF, src.tiles[i*2 + 1]);
}
}
dest.result[0] = minvalF;
dest.result[1] = maxvalF;
}
+104
View File
@@ -0,0 +1,104 @@
/******************************************************************************
* The MIT License (MIT)
*
* Copyright (c) 2014 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.
******************************************************************************/
// compute shaders that figure out the min/max values or histogram in a texture heirarchically
// note that we have to conditionally compile this shader for float/uint/sint as doing that
// dynamically produces a shader with too many temp registers unfortunately.
#version 430 core
#define HGRAM_PIXELS_PER_TILE 64u
#define HGRAM_TILES_PER_BLOCK 32u
#define HGRAM_NUM_BUCKETS 256u
layout(binding=0, std140) writeonly buffer minmaxtiledest
{
vec4 tiles[];
} dest;
layout(binding=2, std140) uniform HistogramCBufferData
{
uint HistogramChannels;
float HistogramMin;
float HistogramMax;
uint HistogramFlags;
float HistogramSlice;
int HistogramMip;
int HistogramSample;
int HistogramNumSamples;
vec3 HistogramTextureResolution;
float Padding3;
} minmax;
layout (binding = 3) uniform sampler2D tex;
layout (local_size_x = HGRAM_TILES_PER_BLOCK, local_size_y = HGRAM_TILES_PER_BLOCK) in;
void main()
{
uvec3 tid = gl_LocalInvocationID;
uvec3 gid = gl_WorkGroupID;
uvec3 texDim = uvec3(minmax.HistogramTextureResolution);
uint blocksX = uint(ceil(float(texDim.x)/float(HGRAM_PIXELS_PER_TILE*HGRAM_TILES_PER_BLOCK)));
uvec2 topleft = (gid.xy*HGRAM_TILES_PER_BLOCK + tid.xy)*HGRAM_PIXELS_PER_TILE;
uint outIdx = (tid.y*HGRAM_TILES_PER_BLOCK + tid.x) + (gid.y*blocksX + gid.x)*(HGRAM_TILES_PER_BLOCK*HGRAM_TILES_PER_BLOCK);
int i=0;
{
vec4 minval = vec4(0,0,0,0);
vec4 maxval = vec4(0,0,0,0);
for(uint y=topleft.y; y < min(texDim.y, topleft.y + HGRAM_PIXELS_PER_TILE); y++)
{
for(uint x=topleft.x; x < min(texDim.x, topleft.x + HGRAM_PIXELS_PER_TILE); x++)
{
vec4 data = textureLod(tex, vec2(x, y) / minmax.HistogramTextureResolution.xy, float(minmax.HistogramMip));
if(i == 0)
{
minval = maxval = data;
}
else
{
minval = min(minval, data);
maxval = max(maxval, data);
}
i++;
}
}
dest.tiles[outIdx*2+0] = minval;
dest.tiles[outIdx*2+1] = maxval;
}
}
+165 -1
View File
@@ -99,6 +99,35 @@ struct meshuniforms
Vec2f pointSpriteSize;
};
// histogram/minmax is calculated in blocks of NxN each with MxM tiles.
// e.g. a tile is 32x32 pixels, then this is arranged in blocks of 32x32 tiles.
// 1 compute thread = 1 tile, 1 compute group = 1 block
//
// NOTE because of this a block can cover more than the texture (think of a 1280x720
// texture covered by 2x1 blocks)
//
// these values are in each dimension
#define HGRAM_PIXELS_PER_TILE 64
#define HGRAM_TILES_PER_BLOCK 32
#define HGRAM_NUM_BUCKETS 256
struct histogramuniforms
{
uint32_t HistogramChannels;
float HistogramMin;
float HistogramMax;
uint32_t HistogramFlags;
float HistogramSlice;
uint32_t HistogramMip;
int HistogramSample;
int HistogramNumSamples;
Vec3f HistogramTextureResolution;
float Padding3;
};
void VulkanDebugManager::GPUBuffer::Create(WrappedVulkan *driver, VkDevice dev, VkDeviceSize size, uint32_t ringSize, uint32_t flags)
{
const VkLayerDispatchTable *vt = ObjDisp(dev);
@@ -125,6 +154,9 @@ void VulkanDebugManager::GPUBuffer::Create(WrappedVulkan *driver, VkDevice dev,
if(flags & eGPUBufferVBuffer)
bufInfo.usage |= VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
if(flags & eGPUBufferSSBO)
bufInfo.usage |= VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
VkResult vkr = vt->CreateBuffer(Unwrap(dev), &bufInfo, &buf);
RDCASSERT(vkr == VK_SUCCESS);
@@ -365,6 +397,25 @@ VulkanDebugManager::VulkanDebugManager(WrappedVulkan *driver, VkDevice dev)
GetResourceManager()->WrapResource(Unwrap(dev), m_TextDescSetLayout);
}
{
VkDescriptorSetLayoutBinding layoutBinding[] = {
{ VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_ALL, NULL, },
{ VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_ALL, NULL, },
{ VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_ALL, NULL, },
{ VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_ALL, NULL, }
};
VkDescriptorSetLayoutCreateInfo descsetLayoutInfo = {
VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, NULL,
ARRAY_COUNT(layoutBinding), &layoutBinding[0],
};
vkr = vt->CreateDescriptorSetLayout(Unwrap(dev), &descsetLayoutInfo, &m_HistogramDescSetLayout);
RDCASSERT(vkr == VK_SUCCESS);
GetResourceManager()->WrapResource(Unwrap(dev), m_HistogramDescSetLayout);
}
VkPipelineLayoutCreateInfo pipeLayoutInfo = {
VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, NULL,
1, UnwrapPtr(m_TexDisplayDescSetLayout),
@@ -404,15 +455,23 @@ VulkanDebugManager::VulkanDebugManager(WrappedVulkan *driver, VkDevice dev)
GetResourceManager()->WrapResource(Unwrap(dev), m_MeshPipeLayout);
pipeLayoutInfo.pSetLayouts = UnwrapPtr(m_HistogramDescSetLayout);
vkr = vt->CreatePipelineLayout(Unwrap(dev), &pipeLayoutInfo, &m_HistogramPipeLayout);
RDCASSERT(vkr == VK_SUCCESS);
GetResourceManager()->WrapResource(Unwrap(dev), m_HistogramPipeLayout);
VkDescriptorTypeCount descPoolTypes[] = {
{ VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1024, },
{ VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1024, },
{ VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1024, },
{ VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1024, },
};
VkDescriptorPoolCreateInfo descpoolInfo = {
VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, NULL,
VK_DESCRIPTOR_POOL_USAGE_ONE_SHOT, 4+ARRAY_COUNT(m_TexDisplayDescSet),
VK_DESCRIPTOR_POOL_USAGE_ONE_SHOT, 6+ARRAY_COUNT(m_TexDisplayDescSet),
ARRAY_COUNT(descPoolTypes), &descPoolTypes[0],
};
@@ -453,6 +512,18 @@ VulkanDebugManager::VulkanDebugManager(WrappedVulkan *driver, VkDevice dev)
RDCASSERT(vkr == VK_SUCCESS);
GetResourceManager()->WrapResource(Unwrap(dev), m_MeshDescSet);
vkr = vt->AllocDescriptorSets(Unwrap(dev), Unwrap(m_DescriptorPool), VK_DESCRIPTOR_SET_USAGE_STATIC, 1,
UnwrapPtr(m_HistogramDescSetLayout), &m_HistogramDescSet[0]);
RDCASSERT(vkr == VK_SUCCESS);
GetResourceManager()->WrapResource(Unwrap(dev), m_HistogramDescSet[0]);
vkr = vt->AllocDescriptorSets(Unwrap(dev), Unwrap(m_DescriptorPool), VK_DESCRIPTOR_SET_USAGE_STATIC, 1,
UnwrapPtr(m_HistogramDescSetLayout), &m_HistogramDescSet[1]);
RDCASSERT(vkr == VK_SUCCESS);
GetResourceManager()->WrapResource(Unwrap(dev), m_HistogramDescSet[1]);
m_GenericUBO.Create(driver, dev, 128, 10, 0);
RDCCOMPILE_ASSERT(sizeof(genericuniforms) <= 128, "outline strip VBO size");
@@ -504,6 +575,9 @@ VulkanDebugManager::VulkanDebugManager(WrappedVulkan *driver, VkDevice dev)
GetEmbeddedResource(meshvs_spv),
GetEmbeddedResource(meshgs_spv),
GetEmbeddedResource(meshfs_spv),
GetEmbeddedResource(minmaxtilecs_spv),
GetEmbeddedResource(minmaxresultcs_spv),
GetEmbeddedResource(histogramcs_spv),
};
VkShaderStage shaderStages[] = {
@@ -517,6 +591,9 @@ VulkanDebugManager::VulkanDebugManager(WrappedVulkan *driver, VkDevice dev)
VK_SHADER_STAGE_VERTEX,
VK_SHADER_STAGE_GEOMETRY,
VK_SHADER_STAGE_FRAGMENT,
VK_SHADER_STAGE_COMPUTE,
VK_SHADER_STAGE_COMPUTE,
VK_SHADER_STAGE_COMPUTE,
};
enum shaderIdx
@@ -531,6 +608,9 @@ VulkanDebugManager::VulkanDebugManager(WrappedVulkan *driver, VkDevice dev)
MESHVS,
MESHGS,
MESHFS,
MINMAXTILECS,
MINMAXRESULTCS,
HISTOGRAMCS,
NUM_SHADERS,
};
@@ -756,6 +836,35 @@ VulkanDebugManager::VulkanDebugManager(WrappedVulkan *driver, VkDevice dev)
GetResourceManager()->WrapResource(Unwrap(dev), m_HighlightBoxPipeline);
VkComputePipelineCreateInfo compPipeInfo = {
VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO, NULL,
{ VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, NULL, VK_SHADER_STAGE_COMPUTE, VK_NULL_HANDLE, NULL },
0, // flags
Unwrap(m_HistogramPipeLayout),
VK_NULL_HANDLE, 0, // base pipeline VkPipeline
};
compPipeInfo.stage.shader = Unwrap(shader[MINMAXTILECS]);
vkr = vt->CreateComputePipelines(Unwrap(dev), VK_NULL_HANDLE, 1, &compPipeInfo, &m_MinMaxTilePipe);
RDCASSERT(vkr == VK_SUCCESS);
GetResourceManager()->WrapResource(Unwrap(dev), m_MinMaxTilePipe);
compPipeInfo.stage.shader = Unwrap(shader[MINMAXRESULTCS]);
vkr = vt->CreateComputePipelines(Unwrap(dev), VK_NULL_HANDLE, 1, &compPipeInfo, &m_MinMaxResultPipe);
RDCASSERT(vkr == VK_SUCCESS);
GetResourceManager()->WrapResource(Unwrap(dev), m_MinMaxResultPipe);
compPipeInfo.stage.shader = Unwrap(shader[HISTOGRAMCS]);
vkr = vt->CreateComputePipelines(Unwrap(dev), VK_NULL_HANDLE, 1, &compPipeInfo, &m_HistogramPipe);
RDCASSERT(vkr == VK_SUCCESS);
GetResourceManager()->WrapResource(Unwrap(dev), m_HistogramPipe);
vt->DestroyRenderPass(Unwrap(dev), RGBA32RP);
vt->DestroyRenderPass(Unwrap(dev), RGBA8RP);
@@ -1099,6 +1208,21 @@ VulkanDebugManager::VulkanDebugManager(WrappedVulkan *driver, VkDevice dev)
memcpy(axisData, axisFrustum, sizeof(axisFrustum));
m_MeshAxisFrustumVB.Unmap(vt, dev);
const uint32_t maxTexDim = 16384;
const uint32_t blockPixSize = HGRAM_PIXELS_PER_TILE*HGRAM_TILES_PER_BLOCK;
const uint32_t maxBlocksNeeded = (maxTexDim*maxTexDim)/(blockPixSize*blockPixSize);
const size_t byteSize = 2*sizeof(Vec4f)*HGRAM_TILES_PER_BLOCK*HGRAM_TILES_PER_BLOCK*maxBlocksNeeded;
m_MinMaxTileResult.Create(driver, dev, byteSize, 1, GPUBuffer::eGPUBufferSSBO);
m_MinMaxResult.Create(driver, dev, sizeof(Vec4f)*2, 1, GPUBuffer::eGPUBufferSSBO);
m_MinMaxReadback.Create(driver, dev, sizeof(Vec4f)*2, 1, GPUBuffer::eGPUBufferReadback);
m_HistogramBuf.Create(driver, dev, sizeof(uint32_t)*HGRAM_NUM_BUCKETS, 1, GPUBuffer::eGPUBufferSSBO);
m_HistogramReadback.Create(driver, dev, sizeof(uint32_t)*HGRAM_NUM_BUCKETS, 1, GPUBuffer::eGPUBufferReadback);
// don't need to ring this, as we hard-sync for readback anyway
m_HistogramUBO.Create(driver, dev, sizeof(histogramuniforms), 1, 0);
VkDescriptorInfo desc[7];
RDCEraseEl(desc);
@@ -1194,6 +1318,9 @@ VulkanDebugManager::~VulkanDebugManager()
GetResourceManager()->ReleaseWrappedResource(m_TextDescSet);
GetResourceManager()->ReleaseWrappedResource(m_MeshDescSet);
for(size_t i=0; i < ARRAY_COUNT(m_HistogramDescSet); i++)
GetResourceManager()->ReleaseWrappedResource(m_HistogramDescSet[i]);
for(size_t i=0; i < ARRAY_COUNT(m_TexDisplayDescSet); i++)
GetResourceManager()->ReleaseWrappedResource(m_TexDisplayDescSet[i]);
@@ -1375,6 +1502,43 @@ VulkanDebugManager::~VulkanDebugManager()
m_OutlineStripVBO.Destroy(vt, dev);
m_GenericUBO.Destroy(vt, dev);
if(m_HistogramDescSetLayout != VK_NULL_HANDLE)
{
vt->DestroyDescriptorSetLayout(Unwrap(dev), Unwrap(m_HistogramDescSetLayout));
GetResourceManager()->ReleaseWrappedResource(m_HistogramDescSetLayout);
}
if(m_HistogramPipeLayout != VK_NULL_HANDLE)
{
vt->DestroyPipelineLayout(Unwrap(dev), Unwrap(m_HistogramPipeLayout));
GetResourceManager()->ReleaseWrappedResource(m_HistogramPipeLayout);
}
if(m_MinMaxResultPipe != VK_NULL_HANDLE)
{
vt->DestroyPipeline(Unwrap(dev), Unwrap(m_MinMaxResultPipe));
GetResourceManager()->ReleaseWrappedResource(m_MinMaxResultPipe);
}
if(m_MinMaxTilePipe != VK_NULL_HANDLE)
{
vt->DestroyPipeline(Unwrap(dev), Unwrap(m_MinMaxTilePipe));
GetResourceManager()->ReleaseWrappedResource(m_MinMaxTilePipe);
}
if(m_HistogramPipe != VK_NULL_HANDLE)
{
vt->DestroyPipeline(Unwrap(dev), Unwrap(m_HistogramPipe));
GetResourceManager()->ReleaseWrappedResource(m_HistogramPipe);
}
m_MinMaxTileResult.Destroy(vt, dev);
m_MinMaxResult.Destroy(vt, dev);
m_MinMaxReadback.Destroy(vt, dev);
m_HistogramBuf.Destroy(vt, dev);
m_HistogramReadback.Destroy(vt, dev);
m_HistogramUBO.Destroy(vt, dev);
// overlay resources are allocated through driver
if(m_OverlayNoDepthFB != VK_NULL_HANDLE)
m_pDriver->vkDestroyFramebuffer(dev, m_OverlayNoDepthFB);
+12
View File
@@ -74,6 +74,7 @@ class VulkanDebugManager
{
eGPUBufferReadback = 0x1,
eGPUBufferVBuffer = 0x2,
eGPUBufferSSBO = 0x4,
};
GPUBuffer() : buf(VK_NULL_HANDLE), mem(VK_NULL_HANDLE) {}
void Create(WrappedVulkan *driver, VkDevice dev, VkDeviceSize size, uint32_t ringSize, uint32_t flags);
@@ -162,6 +163,17 @@ class VulkanDebugManager
GPUBuffer m_MeshUBO, m_MeshBBoxVB, m_MeshAxisFrustumVB;
VkShader m_MeshShaders[3];
VkShaderModule m_MeshModules[3];
GPUBuffer m_MinMaxTileResult; // tile result buffer
GPUBuffer m_MinMaxResult, m_MinMaxReadback; // Vec4f[2] final result buffer
GPUBuffer m_HistogramBuf, m_HistogramReadback; // uint32_t * num buckets buffer
VkDescriptorSetLayout m_HistogramDescSetLayout;
VkPipelineLayout m_HistogramPipeLayout;
VkDescriptorSet m_HistogramDescSet[2];
GPUBuffer m_HistogramUBO;
VkPipeline m_MinMaxResultPipe;
VkPipeline m_MinMaxTilePipe;
VkPipeline m_HistogramPipe;
MeshDisplayPipelines CacheMeshDisplayPipelines(const MeshFormat &primary, const MeshFormat &secondary);
+422 -4
View File
@@ -80,6 +80,27 @@ struct meshuniforms
#define MESHDISPLAY_SECONDARY 0x3
#define MESHDISPLAY_SECONDARY_ALPHA 0x4
#define HGRAM_PIXELS_PER_TILE 64
#define HGRAM_TILES_PER_BLOCK 32
#define HGRAM_NUM_BUCKETS 256
struct histogramuniforms
{
uint32_t HistogramChannels;
float HistogramMin;
float HistogramMax;
uint32_t HistogramFlags;
float HistogramSlice;
uint32_t HistogramMip;
int HistogramSample;
int HistogramNumSamples;
Vec3f HistogramTextureResolution;
float Padding3;
};
VulkanReplay::OutputWindow::OutputWindow() : wnd(NULL_WND_HANDLE), width(0), height(0),
dsimg(VK_NULL_HANDLE), dsmem(VK_NULL_HANDLE)
{
@@ -3133,14 +3154,411 @@ void VulkanReplay::FillCBufferVariables(ResourceId shader, uint32_t cbufSlot, ve
bool VulkanReplay::GetMinMax(ResourceId texid, uint32_t sliceFace, uint32_t mip, uint32_t sample, float *minval, float *maxval)
{
RDCUNIMPLEMENTED("GetMinMax");
return false;
VkDevice dev = m_pDriver->GetDev();
VkCmdBuffer cmd = m_pDriver->GetNextCmd();
const VkLayerDispatchTable *vt = ObjDisp(dev);
ImageLayouts &layouts = m_pDriver->m_ImageLayouts[texid];
VulkanCreationInfo::Image &iminfo = m_pDriver->m_CreationInfo.m_Image[texid];
VkImage liveIm = m_pDriver->GetResourceManager()->GetCurrentHandle<VkImage>(texid);
// VKTODOMED handle multiple subresources with different layouts etc
VkImageLayout origLayout = layouts.subresourceStates[0].newLayout;
VkImageView liveImView = iminfo.view;
if(liveImView == VK_NULL_HANDLE)
{
VkImageViewCreateInfo viewInfo = {
VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, NULL,
Unwrap(liveIm), VK_IMAGE_VIEW_TYPE_2D,
iminfo.format,
{ VK_CHANNEL_SWIZZLE_R, VK_CHANNEL_SWIZZLE_G, VK_CHANNEL_SWIZZLE_B, VK_CHANNEL_SWIZZLE_A },
{ VK_IMAGE_ASPECT_COLOR_BIT, 0, RDCMAX(1U, (uint32_t)iminfo.mipLevels), 0, 1, },
0
};
// Only needed on AMD - does the wrong thing on nvidia - so commented for now while AMD
// drivers aren't on 0.9.2
//if(iminfo.format == VK_FORMAT_B8G8R8A8_UNORM || iminfo.format == VK_FORMAT_B8G8R8A8_SRGB)
//std::swap(viewInfo.channels.r, viewInfo.channels.b);
VkResult vkr = ObjDisp(dev)->CreateImageView(Unwrap(dev), &viewInfo, &iminfo.view);
RDCASSERT(vkr == VK_SUCCESS);
ResourceId viewid = m_pDriver->GetResourceManager()->WrapResource(Unwrap(dev), iminfo.view);
// register as a live-only resource, so it is cleaned up properly
m_pDriver->GetResourceManager()->AddLiveResource(viewid, iminfo.view);
liveImView = iminfo.view;
}
VkDescriptorInfo desc = {0};
desc.imageLayout = VK_IMAGE_LAYOUT_GENERAL;
desc.imageView = Unwrap(liveImView);
desc.sampler = Unwrap(GetDebugManager()->m_PointSampler);
VkDescriptorInfo bufdescs[3];
RDCEraseEl(bufdescs);
GetDebugManager()->m_MinMaxTileResult.FillDescriptor(bufdescs[0]);
GetDebugManager()->m_MinMaxResult.FillDescriptor(bufdescs[1]);
GetDebugManager()->m_HistogramUBO.FillDescriptor(bufdescs[2]);
VkWriteDescriptorSet writeSet[] = {
// first pass on tiles
{
VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, NULL,
Unwrap(GetDebugManager()->m_HistogramDescSet[0]),
0, 0, 1, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &bufdescs[0] // destination = tile result
},
{
VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, NULL,
Unwrap(GetDebugManager()->m_HistogramDescSet[0]),
1, 0, 1, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &bufdescs[0] // source = unused, bind tile result
},
{
VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, NULL,
Unwrap(GetDebugManager()->m_HistogramDescSet[0]),
2, 0, 1, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &bufdescs[2]
},
{
VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, NULL,
Unwrap(GetDebugManager()->m_HistogramDescSet[0]),
3, 0, 1, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &desc
},
// second pass from tiles to result
{
VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, NULL,
Unwrap(GetDebugManager()->m_HistogramDescSet[1]),
0, 0, 1, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &bufdescs[1] // destination = result
},
{
VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, NULL,
Unwrap(GetDebugManager()->m_HistogramDescSet[1]),
1, 0, 1, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &bufdescs[0] // source = tile result
},
{
VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, NULL,
Unwrap(GetDebugManager()->m_HistogramDescSet[1]),
2, 0, 1, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &bufdescs[2]
},
};
vt->UpdateDescriptorSets(Unwrap(dev), ARRAY_COUNT(writeSet), writeSet, 0, NULL);
histogramuniforms *data = (histogramuniforms *)GetDebugManager()->m_HistogramUBO.Map(vt, dev, NULL);
data->HistogramTextureResolution.x = (float)RDCMAX(uint32_t(iminfo.extent.width)>>mip, 1U);
data->HistogramTextureResolution.y = (float)RDCMAX(uint32_t(iminfo.extent.height)>>mip, 1U);
data->HistogramTextureResolution.z = (float)RDCMAX(uint32_t(iminfo.arraySize)>>mip, 1U);
data->HistogramSlice = (float)sliceFace;
data->HistogramMip = (int)mip;
data->HistogramNumSamples = iminfo.samples;
data->HistogramSample = (int)RDCCLAMP(sample, 0U, uint32_t(iminfo.samples)-1);
if(sample == ~0U) data->HistogramSample = -iminfo.samples;
data->HistogramMin = 0.0f;
data->HistogramMax = 1.0f;
data->HistogramChannels = 0xf;
if(iminfo.type == VK_IMAGE_TYPE_3D)
data->HistogramSlice = float(sliceFace)/float(iminfo.extent.depth);
GetDebugManager()->m_HistogramUBO.Unmap(vt, dev);
VkImageMemoryBarrier srcimTrans = {
VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, NULL,
0, 0, origLayout, VK_IMAGE_LAYOUT_GENERAL,
VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED,
Unwrap(liveIm),
{ VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }
};
// ensure all previous writes have completed
srcimTrans.outputMask =
VK_MEMORY_OUTPUT_COLOR_ATTACHMENT_BIT|
VK_MEMORY_OUTPUT_SHADER_WRITE_BIT|
VK_MEMORY_OUTPUT_DEPTH_STENCIL_ATTACHMENT_BIT|
VK_MEMORY_OUTPUT_TRANSFER_BIT;
// before we go reading
srcimTrans.inputMask = VK_MEMORY_INPUT_SHADER_READ_BIT;
VkCmdBufferBeginInfo beginInfo = { VK_STRUCTURE_TYPE_CMD_BUFFER_BEGIN_INFO, NULL, VK_CMD_BUFFER_OPTIMIZE_SMALL_BATCH_BIT | VK_CMD_BUFFER_OPTIMIZE_ONE_TIME_SUBMIT_BIT };
vt->BeginCommandBuffer(Unwrap(cmd), &beginInfo);
void *barrier = (void *)&srcimTrans;
vt->CmdPipelineBarrier(Unwrap(cmd), VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, false, 1, &barrier);
srcimTrans.oldLayout = srcimTrans.newLayout;
srcimTrans.outputMask = 0;
srcimTrans.inputMask = 0;
int blocksX = (int)ceil(iminfo.extent.width/float(HGRAM_PIXELS_PER_TILE*HGRAM_TILES_PER_BLOCK));
int blocksY = (int)ceil(iminfo.extent.height/float(HGRAM_PIXELS_PER_TILE*HGRAM_TILES_PER_BLOCK));
vt->CmdBindPipeline(Unwrap(cmd), VK_PIPELINE_BIND_POINT_COMPUTE, Unwrap(GetDebugManager()->m_MinMaxTilePipe));
vt->CmdBindDescriptorSets(Unwrap(cmd), VK_PIPELINE_BIND_POINT_COMPUTE, Unwrap(GetDebugManager()->m_HistogramPipeLayout),
0, 1, UnwrapPtr(GetDebugManager()->m_HistogramDescSet[0]), 0, NULL);
vt->CmdDispatch(Unwrap(cmd), blocksX, blocksY, 1);
VkBufferMemoryBarrier tilebarrier = {
VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, NULL,
VK_MEMORY_OUTPUT_SHADER_WRITE_BIT, VK_MEMORY_INPUT_SHADER_READ_BIT,
VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED,
Unwrap(GetDebugManager()->m_MinMaxTileResult.buf),
0, GetDebugManager()->m_MinMaxTileResult.totalsize,
};
// image layout back to normal
srcimTrans.newLayout = origLayout;
vt->CmdPipelineBarrier(Unwrap(cmd), VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, false, 1, &barrier);
// ensure shader writes complete before coalescing the tiles
barrier = (void *)&tilebarrier;
vt->CmdPipelineBarrier(Unwrap(cmd), VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, false, 1, &barrier);
vt->CmdBindPipeline(Unwrap(cmd), VK_PIPELINE_BIND_POINT_COMPUTE, Unwrap(GetDebugManager()->m_MinMaxResultPipe));
vt->CmdBindDescriptorSets(Unwrap(cmd), VK_PIPELINE_BIND_POINT_COMPUTE, Unwrap(GetDebugManager()->m_HistogramPipeLayout),
0, 1, UnwrapPtr(GetDebugManager()->m_HistogramDescSet[1]), 0, NULL);
vt->CmdDispatch(Unwrap(cmd), 1, 1, 1);
// ensure shader writes complete before copying back to readback buffer
tilebarrier.inputMask = VK_MEMORY_INPUT_TRANSFER_BIT;
tilebarrier.buffer = Unwrap(GetDebugManager()->m_MinMaxResult.buf);
tilebarrier.size = GetDebugManager()->m_MinMaxResult.totalsize;
vt->CmdPipelineBarrier(Unwrap(cmd), VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, false, 1, &barrier);
VkBufferCopy bufcopy = {
0, 0, GetDebugManager()->m_MinMaxResult.totalsize,
};
vt->CmdCopyBuffer(Unwrap(cmd), Unwrap(GetDebugManager()->m_MinMaxResult.buf), Unwrap(GetDebugManager()->m_MinMaxReadback.buf), 1, &bufcopy);
// wait for copy to complete before mapping
tilebarrier.outputMask = VK_MEMORY_OUTPUT_TRANSFER_BIT;
tilebarrier.inputMask = VK_MEMORY_INPUT_HOST_READ_BIT;
tilebarrier.buffer = Unwrap(GetDebugManager()->m_MinMaxReadback.buf);
tilebarrier.size = GetDebugManager()->m_MinMaxResult.totalsize;
vt->CmdPipelineBarrier(Unwrap(cmd), VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, false, 1, &barrier);
vt->EndCommandBuffer(Unwrap(cmd));
// submit cmds and wait for idle so we can readback
m_pDriver->SubmitCmds();
m_pDriver->FlushQ();
Vec4f *minmax = (Vec4f *)GetDebugManager()->m_MinMaxReadback.Map(vt, dev, NULL);
minval[0] = minmax[0].x;
minval[1] = minmax[0].y;
minval[2] = minmax[0].z;
minval[3] = minmax[0].w;
maxval[0] = minmax[1].x;
maxval[1] = minmax[1].y;
maxval[2] = minmax[1].z;
maxval[3] = minmax[1].w;
GetDebugManager()->m_MinMaxReadback.Unmap(vt, dev);
return true;
}
bool VulkanReplay::GetHistogram(ResourceId texid, uint32_t sliceFace, uint32_t mip, uint32_t sample, float minval, float maxval, bool channels[4], vector<uint32_t> &histogram)
{
RDCUNIMPLEMENTED("GetHistogram");
return false;
if(minval >= maxval) return false;
VkDevice dev = m_pDriver->GetDev();
VkCmdBuffer cmd = m_pDriver->GetNextCmd();
const VkLayerDispatchTable *vt = ObjDisp(dev);
ImageLayouts &layouts = m_pDriver->m_ImageLayouts[texid];
VulkanCreationInfo::Image &iminfo = m_pDriver->m_CreationInfo.m_Image[texid];
VkImage liveIm = m_pDriver->GetResourceManager()->GetCurrentHandle<VkImage>(texid);
// VKTODOMED handle multiple subresources with different layouts etc
VkImageLayout origLayout = layouts.subresourceStates[0].newLayout;
VkImageView liveImView = iminfo.view;
if(liveImView == VK_NULL_HANDLE)
{
VkImageViewCreateInfo viewInfo = {
VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, NULL,
Unwrap(liveIm), VK_IMAGE_VIEW_TYPE_2D,
iminfo.format,
{ VK_CHANNEL_SWIZZLE_R, VK_CHANNEL_SWIZZLE_G, VK_CHANNEL_SWIZZLE_B, VK_CHANNEL_SWIZZLE_A },
{ VK_IMAGE_ASPECT_COLOR_BIT, 0, RDCMAX(1U, (uint32_t)iminfo.mipLevels), 0, 1, },
0
};
// Only needed on AMD - does the wrong thing on nvidia - so commented for now while AMD
// drivers aren't on 0.9.2
//if(iminfo.format == VK_FORMAT_B8G8R8A8_UNORM || iminfo.format == VK_FORMAT_B8G8R8A8_SRGB)
//std::swap(viewInfo.channels.r, viewInfo.channels.b);
VkResult vkr = ObjDisp(dev)->CreateImageView(Unwrap(dev), &viewInfo, &iminfo.view);
RDCASSERT(vkr == VK_SUCCESS);
ResourceId viewid = m_pDriver->GetResourceManager()->WrapResource(Unwrap(dev), iminfo.view);
// register as a live-only resource, so it is cleaned up properly
m_pDriver->GetResourceManager()->AddLiveResource(viewid, iminfo.view);
liveImView = iminfo.view;
}
VkDescriptorInfo desc = {0};
desc.imageLayout = VK_IMAGE_LAYOUT_GENERAL;
desc.imageView = Unwrap(liveImView);
desc.sampler = Unwrap(GetDebugManager()->m_PointSampler);
VkDescriptorInfo bufdescs[2];
RDCEraseEl(bufdescs);
GetDebugManager()->m_HistogramBuf.FillDescriptor(bufdescs[0]);
GetDebugManager()->m_HistogramUBO.FillDescriptor(bufdescs[1]);
VkWriteDescriptorSet writeSet[] = {
// histogram pass
{
VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, NULL,
Unwrap(GetDebugManager()->m_HistogramDescSet[0]),
0, 0, 1, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &bufdescs[0] // destination = histogram result
},
{
VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, NULL,
Unwrap(GetDebugManager()->m_HistogramDescSet[0]),
1, 0, 1, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &bufdescs[0] // source = unused, bind histogram result
},
{
VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, NULL,
Unwrap(GetDebugManager()->m_HistogramDescSet[0]),
2, 0, 1, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &bufdescs[1]
},
{
VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, NULL,
Unwrap(GetDebugManager()->m_HistogramDescSet[0]),
3, 0, 1, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &desc
},
};
vt->UpdateDescriptorSets(Unwrap(dev), ARRAY_COUNT(writeSet), writeSet, 0, NULL);
histogramuniforms *data = (histogramuniforms *)GetDebugManager()->m_HistogramUBO.Map(vt, dev, NULL);
data->HistogramTextureResolution.x = (float)RDCMAX(uint32_t(iminfo.extent.width)>>mip, 1U);
data->HistogramTextureResolution.y = (float)RDCMAX(uint32_t(iminfo.extent.height)>>mip, 1U);
data->HistogramTextureResolution.z = (float)RDCMAX(uint32_t(iminfo.arraySize)>>mip, 1U);
data->HistogramSlice = (float)sliceFace;
data->HistogramMip = (int)mip;
data->HistogramNumSamples = iminfo.samples;
data->HistogramSample = (int)RDCCLAMP(sample, 0U, uint32_t(iminfo.samples)-1);
if(sample == ~0U) data->HistogramSample = -iminfo.samples;
data->HistogramMin = minval;
data->HistogramMax = maxval;
uint32_t chans = 0;
if(channels[0]) chans |= 0x1;
if(channels[1]) chans |= 0x2;
if(channels[2]) chans |= 0x4;
if(channels[3]) chans |= 0x8;
data->HistogramChannels = chans;
data->HistogramFlags = 0;
if(iminfo.type == VK_IMAGE_TYPE_3D)
data->HistogramSlice = float(sliceFace)/float(iminfo.extent.depth);
GetDebugManager()->m_HistogramUBO.Unmap(vt, dev);
VkImageMemoryBarrier srcimTrans = {
VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, NULL,
0, 0, origLayout, VK_IMAGE_LAYOUT_GENERAL,
VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED,
Unwrap(liveIm),
{ VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }
};
// ensure all previous writes have completed
srcimTrans.outputMask =
VK_MEMORY_OUTPUT_COLOR_ATTACHMENT_BIT|
VK_MEMORY_OUTPUT_SHADER_WRITE_BIT|
VK_MEMORY_OUTPUT_DEPTH_STENCIL_ATTACHMENT_BIT|
VK_MEMORY_OUTPUT_TRANSFER_BIT;
// before we go reading
srcimTrans.inputMask = VK_MEMORY_INPUT_SHADER_READ_BIT;
VkCmdBufferBeginInfo beginInfo = { VK_STRUCTURE_TYPE_CMD_BUFFER_BEGIN_INFO, NULL, VK_CMD_BUFFER_OPTIMIZE_SMALL_BATCH_BIT | VK_CMD_BUFFER_OPTIMIZE_ONE_TIME_SUBMIT_BIT };
vt->BeginCommandBuffer(Unwrap(cmd), &beginInfo);
void *barrier = (void *)&srcimTrans;
vt->CmdPipelineBarrier(Unwrap(cmd), VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, false, 1, &barrier);
srcimTrans.oldLayout = srcimTrans.newLayout;
srcimTrans.outputMask = 0;
srcimTrans.inputMask = 0;
int blocksX = (int)ceil(iminfo.extent.width/float(HGRAM_PIXELS_PER_TILE*HGRAM_TILES_PER_BLOCK));
int blocksY = (int)ceil(iminfo.extent.height/float(HGRAM_PIXELS_PER_TILE*HGRAM_TILES_PER_BLOCK));
vt->CmdFillBuffer(Unwrap(cmd), Unwrap(GetDebugManager()->m_HistogramBuf.buf), 0, GetDebugManager()->m_HistogramBuf.totalsize, 0);
vt->CmdBindPipeline(Unwrap(cmd), VK_PIPELINE_BIND_POINT_COMPUTE, Unwrap(GetDebugManager()->m_HistogramPipe));
vt->CmdBindDescriptorSets(Unwrap(cmd), VK_PIPELINE_BIND_POINT_COMPUTE, Unwrap(GetDebugManager()->m_HistogramPipeLayout),
0, 1, UnwrapPtr(GetDebugManager()->m_HistogramDescSet[0]), 0, NULL);
vt->CmdDispatch(Unwrap(cmd), blocksX, blocksY, 1);
VkBufferMemoryBarrier tilebarrier = {
VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, NULL,
VK_MEMORY_OUTPUT_SHADER_WRITE_BIT, VK_MEMORY_INPUT_TRANSFER_BIT,
VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED,
Unwrap(GetDebugManager()->m_HistogramBuf.buf),
0, GetDebugManager()->m_HistogramBuf.totalsize,
};
// image layout back to normal
srcimTrans.newLayout = origLayout;
vt->CmdPipelineBarrier(Unwrap(cmd), VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, false, 1, &barrier);
// ensure shader writes complete before copying to readback buf
barrier = (void *)&tilebarrier;
vt->CmdPipelineBarrier(Unwrap(cmd), VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, false, 1, &barrier);
VkBufferCopy bufcopy = {
0, 0, GetDebugManager()->m_HistogramBuf.totalsize,
};
vt->CmdCopyBuffer(Unwrap(cmd), Unwrap(GetDebugManager()->m_HistogramBuf.buf), Unwrap(GetDebugManager()->m_HistogramReadback.buf), 1, &bufcopy);
// wait for copy to complete before mapping
tilebarrier.outputMask = VK_MEMORY_OUTPUT_TRANSFER_BIT;
tilebarrier.inputMask = VK_MEMORY_INPUT_HOST_READ_BIT;
tilebarrier.buffer = Unwrap(GetDebugManager()->m_HistogramReadback.buf);
tilebarrier.size = GetDebugManager()->m_HistogramReadback.totalsize;
vt->CmdPipelineBarrier(Unwrap(cmd), VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, false, 1, &barrier);
vt->EndCommandBuffer(Unwrap(cmd));
// submit cmds and wait for idle so we can readback
m_pDriver->SubmitCmds();
m_pDriver->FlushQ();
uint32_t *buckets = (uint32_t *)GetDebugManager()->m_HistogramReadback.Map(vt, dev, NULL);
histogram.assign(buckets, buckets+HGRAM_NUM_BUCKETS);
GetDebugManager()->m_HistogramReadback.Unmap(vt, dev);
return true;
}
void VulkanReplay::InitPostVSBuffers(uint32_t frameID, uint32_t eventID)
+6
View File
@@ -367,12 +367,18 @@
<None Include="data\spv\generic.vert" />
<None Include="data\spv\genericfs.spv" />
<None Include="data\spv\genericvs.spv" />
<None Include="data\spv\histogram.comp" />
<None Include="data\spv\histogramcs.spv" />
<None Include="data\spv\mesh.frag" />
<None Include="data\spv\mesh.geom" />
<None Include="data\spv\mesh.vert" />
<None Include="data\spv\meshfs.spv" />
<None Include="data\spv\meshgs.spv" />
<None Include="data\spv\meshvs.spv" />
<None Include="data\spv\minmaxresult.comp" />
<None Include="data\spv\minmaxresultcs.spv" />
<None Include="data\spv\minmaxtile.comp" />
<None Include="data\spv\minmaxtilecs.spv" />
<None Include="data\spv\texdisplay.frag" />
<None Include="data\spv\texdisplayfs.spv" />
<None Include="data\spv\text.frag" />
+18
View File
@@ -496,6 +496,24 @@
<None Include="data\spv\meshfs.spv">
<Filter>Resources\spv</Filter>
</None>
<None Include="data\spv\histogram.comp">
<Filter>Resources\spv</Filter>
</None>
<None Include="data\spv\histogramcs.spv">
<Filter>Resources\spv</Filter>
</None>
<None Include="data\spv\minmaxresult.comp">
<Filter>Resources\spv</Filter>
</None>
<None Include="data\spv\minmaxresultcs.spv">
<Filter>Resources\spv</Filter>
</None>
<None Include="data\spv\minmaxtile.comp">
<Filter>Resources\spv</Filter>
</None>
<None Include="data\spv\minmaxtilecs.spv">
<Filter>Resources\spv</Filter>
</None>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="data\renderdoc.rc">