diff --git a/renderdoc/Makefile b/renderdoc/Makefile index 1cfc67144..df23a2f42 100644 --- a/renderdoc/Makefile +++ b/renderdoc/Makefile @@ -57,6 +57,7 @@ os/linux/linux_stringio.o \ os/linux/linux_threading.o \ hooks/linux_libentry.o DATA=data/glsl/debuguniforms.ho \ +data/glsl/texsample.ho \ data/glsl/blit.frago \ data/glsl/blit.verto \ data/glsl/texdisplay.frago \ @@ -66,6 +67,7 @@ data/glsl/generic.verto \ data/glsl/mesh.verto \ data/glsl/text.verto \ data/glsl/text.frago \ +data/glsl/histogram.compo \ data/sourcecodepro.ttfo .PHONY: all @@ -83,25 +85,28 @@ $(OBJDIR)/%.o: %.c # objcopy needs to be run in with paths in current directory # to produce the right symbol names +OBJGEN = \ +mkdir -p $$(dirname $@); \ +cd $$(dirname $<); \ +objcopy --input binary --output elf64-x86-64 --binary-architecture i386 $$(basename $<) $$(basename $@); \ +cd - > /dev/null 2>&1; \ +mv $$(dirname $<)/$$(basename $@) $@; + $(OBJDIR)/%.verto: %.vert - @mkdir -p $$(dirname $@) - cd $$(dirname $<) && objcopy --input binary --output elf64-x86-64 --binary-architecture i386 $$(basename $<) $$(basename $@) - @mv $$(dirname $<)/$$(basename $@) $@ - + @echo Object building $@ + @$(OBJGEN) $(OBJDIR)/%.frago: %.frag - @mkdir -p $$(dirname $@) - cd $$(dirname $<) && objcopy --input binary --output elf64-x86-64 --binary-architecture i386 $$(basename $<) $$(basename $@) - @mv $$(dirname $<)/$$(basename $@) $@ - + @echo Object building $@ + @$(OBJGEN) +$(OBJDIR)/%.compo: %.comp + @echo Object building $@ + @$(OBJGEN) $(OBJDIR)/%.ttfo: %.ttf - @mkdir -p $$(dirname $@) - cd $$(dirname $<) && objcopy --input binary --output elf64-x86-64 --binary-architecture i386 $$(basename $<) $$(basename $@) - @mv $$(dirname $<)/$$(basename $@) $@ - + @echo Object building $@ + @$(OBJGEN) $(OBJDIR)/%.ho: %.h - @mkdir -p $$(dirname $@) - cd $$(dirname $<) && objcopy --input binary --output elf64-x86-64 --binary-architecture i386 $$(basename $<) $$(basename $@) - @mv $$(dirname $<)/$$(basename $@) $@ + @echo Object building $@ + @$(OBJGEN) OBJDIR_OBJECTS=$(addprefix $(OBJDIR)/, $(OBJECTS)) OBJDIR_DATA=$(addprefix $(OBJDIR)/, $(DATA)) diff --git a/renderdoc/data/glsl/debuguniforms.h b/renderdoc/data/glsl/debuguniforms.h index 419d08e8d..c3ea23b78 100644 --- a/renderdoc/data/glsl/debuguniforms.h +++ b/renderdoc/data/glsl/debuguniforms.h @@ -30,6 +30,7 @@ #define vec2 Vec2f #define vec3 Vec3f #define vec4 Vec4f +#define uint uint32_t #define BINDING(b) @@ -72,6 +73,22 @@ BINDING(0) uniform FontUniforms vec2 FontScreenAspect; }; +BINDING(0) uniform HistogramCBufferData +{ + uint HistogramChannels; + float HistogramMin; + float HistogramMax; + uint HistogramFlags; + + float HistogramSlice; + int HistogramMip; + int HistogramSample; + uint Padding2; + + vec3 HistogramTextureResolution; + float Padding3; +}; + // some constants available to both C++ and GLSL for configuring display #define CUBEMAP_FACE_POS_X 0 #define CUBEMAP_FACE_NEG_X 1 @@ -93,3 +110,17 @@ BINDING(0) uniform FontUniforms #define TEXDISPLAY_SINT_TEX 0x10 #define TEXDISPLAY_DEPTH_TEX 0x20 + +// 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 + diff --git a/renderdoc/data/glsl/histogram.comp b/renderdoc/data/glsl/histogram.comp new file mode 100644 index 000000000..97a4113f9 --- /dev/null +++ b/renderdoc/data/glsl/histogram.comp @@ -0,0 +1,243 @@ +/****************************************************************************** + * 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. + +#extension GL_ARB_compute_shader : require +#extension GL_ARB_shader_storage_buffer_object : require + +#if RENDERDOC_TileMinMaxCS + +layout(binding=0) writeonly buffer minmaxtiledest +{ +#if UINT_TEX + uvec4 tiles[]; +#elif SINT_TEX + ivec4 tiles[]; +#else + vec4 tiles[]; +#endif +} dest; + +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; + + int texType = SHADER_RESTYPE; + + uvec3 texDim = uvec3(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; + +#if UINT_TEX + { + uvec4 minval = uvec4(0,0,0,0); + uvec4 maxval = uvec4(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++) + { + uvec4 data = SampleTextureUInt4(vec2(x, y), texType, false, + HistogramMip, HistogramSlice); + // HistogramSample, texDim + + 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; + } +#elif SINT_TEX + { + ivec4 minval = ivec4(0,0,0,0); + ivec4 maxval = ivec4(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++) + { + ivec4 data = SampleTextureSInt4(vec2(x, y), texType, false, + HistogramMip, HistogramSlice); + // HistogramSample, texDim + + 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; + } +#else + { + 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 = SampleTextureFloat4(vec2(x, y), RESTYPE_TEX2D, false, true, + HistogramMip, HistogramSlice); + // HistogramSample, texDim + + 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; + } +#endif +} + +#endif // #if RENDERDOC_TileMinMaxCS + + +#if RENDERDOC_ResultMinMaxCS + +layout(binding=0) writeonly buffer minmaxresultdest +{ +#if UINT_TEX + uvec4 result[2]; +#elif SINT_TEX + ivec4 result[2]; +#else + vec4 result[2]; +#endif +} dest; + +layout(binding=1) readonly buffer minmaxtilesrc +{ +#if UINT_TEX + uvec4 tiles[]; +#elif SINT_TEX + ivec4 tiles[]; +#else + vec4 tiles[]; +#endif +} src; + +layout (local_size_x = 1) in; + +void main() +{ + uvec3 texDim = uvec3(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))); + +#if UINT_TEX + uvec4 minvalU = src.tiles[0]; + uvec4 maxvalU = src.tiles[1]; +#elif SINT_TEX + ivec4 minvalI = src.tiles[0]; + ivec4 maxvalI = src.tiles[1]; +#else + vec4 minvalF = src.tiles[0]; + vec4 maxvalF = src.tiles[1]; +#endif + + // 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) + { +#if UINT_TEX + minvalU = min(minvalU, src.tiles[i*2 + 0]); + maxvalU = max(maxvalU, src.tiles[i*2 + 1]); +#elif SINT_TEX + minvalI = min(minvalI, src.tiles[i*2 + 0]); + maxvalI = max(maxvalI, src.tiles[i*2 + 1]); +#else + minvalF = min(minvalF, src.tiles[i*2 + 0]); + maxvalF = max(maxvalF, src.tiles[i*2 + 1]); +#endif + } + } + +#if UINT_TEX + dest.result[0] = minvalU; + dest.result[1] = maxvalU; +#elif SINT_TEX + dest.result[0] = minvalI; + dest.result[1] = maxvalI; +#else + dest.result[0] = minvalF; + dest.result[1] = maxvalF; +#endif +} + +#endif // #if RENDERDOC_ResultMinMaxCS diff --git a/renderdoc/data/glsl/texdisplay.frag b/renderdoc/data/glsl/texdisplay.frag index fd2d9b441..f49e59e71 100644 --- a/renderdoc/data/glsl/texdisplay.frag +++ b/renderdoc/data/glsl/texdisplay.frag @@ -22,248 +22,8 @@ * THE SOFTWARE. ******************************************************************************/ -layout (binding = 1) uniform sampler1D tex1D; -layout (binding = 2) uniform sampler2D tex2D; -layout (binding = 3) uniform sampler3D tex3D; -layout (binding = 4) uniform samplerCube texCube; -layout (binding = 5) uniform sampler1DArray tex1DArray; -layout (binding = 6) uniform sampler2DArray tex2DArray; -layout (binding = 7) uniform samplerCubeArray texCubeArray; - -layout (binding = 9) uniform usampler1D texUInt1D; -layout (binding = 10) uniform usampler2D texUInt2D; -layout (binding = 11) uniform usampler3D texUInt3D; -layout (binding = 13) uniform usampler1DArray texUInt1DArray; -layout (binding = 14) uniform usampler2DArray texUInt2DArray; - -layout (binding = 16) uniform isampler1D texSInt1D; -layout (binding = 17) uniform isampler2D texSInt2D; -layout (binding = 18) uniform isampler3D texSInt3D; -layout (binding = 20) uniform isampler1DArray texSInt1DArray; -layout (binding = 21) uniform isampler2DArray texSInt2DArray; - layout (location = 0) out vec4 color_out; -vec3 CalcCubeCoord(vec2 uv, int face) -{ - // Map UVs to [-0.5, 0.5] and rotate - uv -= vec2(0.5); - vec3 coord; - if (face == CUBEMAP_FACE_POS_X) - coord = vec3(0.5, uv.y, -uv.x); - else if (face == CUBEMAP_FACE_NEG_X) - coord = vec3(-0.5, -uv.y, uv.x); - else if (face == CUBEMAP_FACE_POS_Y) - coord = vec3(uv.x, 0.5, uv.y); - else if (face == CUBEMAP_FACE_NEG_Y) - coord = vec3(uv.x, -0.5, -uv.y); - else if (face == CUBEMAP_FACE_POS_Z) - coord = vec3(uv.x, -uv.y, 0.5); - else // face == CUBEMAP_FACE_NEG_Z - coord = vec3(-uv.x, -uv.y, -0.5); - return coord; -} - -uvec4 SampleTextureUInt4(vec2 pos, int type, bool flipY, int mipLevel, float slice) -{ - uvec4 col; - if (type == RESTYPE_TEX1D) - { - int size = textureSize(texUInt1D, mipLevel); - if (pos.x < 0 || pos.y < 0 || pos.x > size) discard; - - col = texelFetch(texUInt1D, int(pos.x), mipLevel); - } - else if (type == RESTYPE_TEX1DARRAY) - { - ivec2 size = textureSize(texUInt1DArray, mipLevel); - if (pos.x < 0 || pos.y < 0 || pos.x > size.x) discard; - - col = texelFetch(texUInt1DArray, ivec2(pos.x, slice), mipLevel); - } - else if (type == RESTYPE_TEX2D) - { - ivec2 size = textureSize(texUInt2D, mipLevel); - if (pos.x < 0 || pos.y < 0 || pos.x > size.x || pos.y > size.y) discard; - - if (flipY) - pos.y = size.y - pos.y; - - col = texelFetch(texUInt2D, ivec2(pos), mipLevel); - } - else if (type == RESTYPE_TEX2DARRAY) - { - ivec3 size = textureSize(texUInt2DArray, mipLevel); - if (pos.x < 0 || pos.y < 0 || pos.x > size.x || pos.y > size.y) discard; - - if (flipY) - pos.y = size.y - pos.y; - - col = texelFetch(texUInt2DArray, ivec3(pos, slice), mipLevel); - } - else // if (type == RESTYPE_TEX3D) - { - ivec3 size = textureSize(texUInt3D, mipLevel); - if (pos.x < 0 || pos.y < 0 || pos.x > size.x || pos.y > size.y) discard; - - if (flipY) - pos.y = size.y - pos.y; - - col = texelFetch(texUInt3D, ivec3(pos, slice), mipLevel); - } - - return col; -} - -ivec4 SampleTextureSInt4(vec2 pos, int type, bool flipY, int mipLevel, float slice) -{ - ivec4 col; - if (type == RESTYPE_TEX1D) - { - int size = textureSize(texSInt1D, mipLevel); - if (pos.x < 0 || pos.y < 0 || pos.x > size) discard; - - col = texelFetch(texSInt1D, int(pos.x), mipLevel); - } - else if (type == RESTYPE_TEX1DARRAY) - { - ivec2 size = textureSize(texSInt1DArray, mipLevel); - if (pos.x < 0 || pos.y < 0 || pos.x > size.x) discard; - - col = texelFetch(texSInt1DArray, ivec2(pos.x, slice), mipLevel); - } - else if (type == RESTYPE_TEX2D) - { - ivec2 size = textureSize(texSInt2D, mipLevel); - if (pos.x < 0 || pos.y < 0 || pos.x > size.x || pos.y > size.y) discard; - - if (flipY) - pos.y = size.y - pos.y; - - col = texelFetch(texSInt2D, ivec2(pos), mipLevel); - } - else if (type == RESTYPE_TEX2DARRAY) - { - ivec3 size = textureSize(texSInt2DArray, mipLevel); - if (pos.x < 0 || pos.y < 0 || pos.x > size.x || pos.y > size.y) discard; - - if (flipY) - pos.y = size.y - pos.y; - - col = texelFetch(texSInt2DArray, ivec3(pos, slice), mipLevel); - } - else // if (type == RESTYPE_TEX3D) - { - ivec3 size = textureSize(texSInt3D, mipLevel); - if (pos.x < 0 || pos.y < 0 || pos.x > size.x || pos.y > size.y) discard; - - if (flipY) - pos.y = size.y - pos.y; - - col = texelFetch(texSInt3D, ivec3(pos, slice), mipLevel); - } - - return col; -} - - -vec4 SampleTextureFloat4(vec2 pos, int type, bool flipY, bool linearSample, int mipLevel, float slice) -{ - vec4 col; - if (type == RESTYPE_TEX1D) - { - int size = textureSize(tex1D, mipLevel); - if (pos.x < 0 || pos.y < 0 || pos.x > size) discard; - - if (linearSample) - col = texture(tex1D, pos.x / size); - else - col = texelFetch(tex1D, int(pos.x), mipLevel); - } - else if (type == RESTYPE_TEX1DARRAY) - { - ivec2 size = textureSize(tex1DArray, mipLevel); - if (pos.x < 0 || pos.y < 0 || pos.x > size.x) discard; - - if (linearSample) - col = texture(tex1DArray, vec2(pos.x / size.x, slice)); - else - col = texelFetch(tex1DArray, ivec2(pos.x, slice), mipLevel); - } - else if (type == RESTYPE_TEX2D) - { - ivec2 size = textureSize(tex2D, mipLevel); - if (pos.x < 0 || pos.y < 0 || pos.x > size.x || pos.y > size.y) discard; - - if (flipY) - pos.y = size.y - pos.y; - - if (linearSample) - col = texture(tex2D, pos / size); - else - col = texelFetch(tex2D, ivec2(pos), mipLevel); - } - else if (type == RESTYPE_TEX2DARRAY) - { - ivec3 size = textureSize(tex2DArray, mipLevel); - if (pos.x < 0 || pos.y < 0 || pos.x > size.x || pos.y > size.y) discard; - - if (flipY) - pos.y = size.y - pos.y; - - if (linearSample) - col = texture(tex2DArray, vec3(pos / size.xy, slice)); - else - col = texelFetch(tex2DArray, ivec3(pos, slice), mipLevel); - } - else if (type == RESTYPE_TEX3D) - { - ivec3 size = textureSize(tex3D, mipLevel); - if (pos.x < 0 || pos.y < 0 || pos.x > size.x || pos.y > size.y) discard; - - if (flipY) - pos.y = size.y - pos.y; - - if (linearSample) - col = texture(tex3D, vec3(pos / size.xy, slice)); - else - col = texelFetch(tex3D, ivec3(pos, slice), mipLevel); - } - else if (type == RESTYPE_TEXCUBE) - { - ivec2 size = textureSize(texCube, mipLevel); - if (pos.x < 0 || pos.y < 0 || pos.x > size.x || pos.y > size.y) discard; - - if (flipY) - pos.y = size.y - pos.y; - - vec3 cubeCoord = CalcCubeCoord(pos / size, int(slice)); - - if (linearSample) - col = texture(texCube, cubeCoord); - else - col = textureLod(texCube, cubeCoord, mipLevel); - } - else // type == RESTYPE_TEXCUBEARRAY - { - ivec3 size = textureSize(texCubeArray, mipLevel); - if (pos.x < 0 || pos.y < 0 || pos.x > size.x || pos.y > size.y) discard; - - if (flipY) - pos.y = size.y - pos.y; - - vec3 cubeCoord = CalcCubeCoord(pos / size.xy, int(slice) % 6); - vec4 arrayCoord = vec4(cubeCoord, int(Slice) / 6); - - if (linearSample) - col = texture(texCubeArray, arrayCoord); - else - col = textureLod(texCubeArray, arrayCoord, mipLevel); - } - - return col; -} - void main(void) { bool uintTex = (OutputDisplayFormat & TEXDISPLAY_UINT_TEX) != 0; @@ -277,18 +37,35 @@ void main(void) // calc screen co-ords with origin top left, modified by Position vec2 scr = vec2(gl_FragCoord.x, OutputRes.y - gl_FragCoord.y) - Position.xy; + scr /= Scale; + + int texType = (OutputDisplayFormat & TEXDISPLAY_TYPEMASK); + + if(texType == RESTYPE_TEX1D || texType == RESTYPE_TEX1DARRAY) + { + if(scr.x < 0.0f || scr.x > TextureResolutionPS.x) + discard; + } + else + { + if(scr.x < 0.0f || scr.y < 0.0f || + scr.x > TextureResolutionPS.x || scr.y > TextureResolutionPS.y) + discard; + } + // sample the texture. if (uintTex) { - ucol = SampleTextureUInt4(scr / Scale, OutputDisplayFormat & TEXDISPLAY_TYPEMASK, FlipY == 0, int(MipLevel), Slice); + ucol = SampleTextureUInt4(scr, texType, FlipY == 0, int(MipLevel), Slice); } else if (sintTex) { - scol = SampleTextureSInt4(scr / Scale, OutputDisplayFormat & TEXDISPLAY_TYPEMASK, FlipY == 0, int(MipLevel), Slice); + scol = SampleTextureSInt4(scr, texType, FlipY == 0, int(MipLevel), Slice); } else { col = SampleTextureFloat4(scr / Scale, OutputDisplayFormat & TEXDISPLAY_TYPEMASK, FlipY == 0, (Scale < 1.0 && MipLevel == 0.0 && !depthTex), int(MipLevel), Slice); + col = SampleTextureFloat4(scr, texType, FlipY == 0, (Scale < 1.0 && MipLevel == 0.0 && !depthTex), int(MipLevel), Slice); } if(RawOutput != 0) diff --git a/renderdoc/data/glsl/texsample.h b/renderdoc/data/glsl/texsample.h new file mode 100644 index 000000000..efa4e18f4 --- /dev/null +++ b/renderdoc/data/glsl/texsample.h @@ -0,0 +1,246 @@ +/****************************************************************************** + * 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. + ******************************************************************************/ + +layout (binding = 1) uniform sampler1D tex1D; +layout (binding = 2) uniform sampler2D tex2D; +layout (binding = 3) uniform sampler3D tex3D; +layout (binding = 4) uniform samplerCube texCube; +layout (binding = 5) uniform sampler1DArray tex1DArray; +layout (binding = 6) uniform sampler2DArray tex2DArray; +layout (binding = 7) uniform samplerCubeArray texCubeArray; + +layout (binding = 9) uniform usampler1D texUInt1D; +layout (binding = 10) uniform usampler2D texUInt2D; +layout (binding = 11) uniform usampler3D texUInt3D; +layout (binding = 13) uniform usampler1DArray texUInt1DArray; +layout (binding = 14) uniform usampler2DArray texUInt2DArray; + +layout (binding = 16) uniform isampler1D texSInt1D; +layout (binding = 17) uniform isampler2D texSInt2D; +layout (binding = 18) uniform isampler3D texSInt3D; +layout (binding = 20) uniform isampler1DArray texSInt1DArray; +layout (binding = 21) uniform isampler2DArray texSInt2DArray; + +vec3 CalcCubeCoord(vec2 uv, int face) +{ + // Map UVs to [-0.5, 0.5] and rotate + uv -= vec2(0.5); + vec3 coord; + if (face == CUBEMAP_FACE_POS_X) + coord = vec3(0.5, uv.y, -uv.x); + else if (face == CUBEMAP_FACE_NEG_X) + coord = vec3(-0.5, -uv.y, uv.x); + else if (face == CUBEMAP_FACE_POS_Y) + coord = vec3(uv.x, 0.5, uv.y); + else if (face == CUBEMAP_FACE_NEG_Y) + coord = vec3(uv.x, -0.5, -uv.y); + else if (face == CUBEMAP_FACE_POS_Z) + coord = vec3(uv.x, -uv.y, 0.5); + else // face == CUBEMAP_FACE_NEG_Z + coord = vec3(-uv.x, -uv.y, -0.5); + return coord; +} + +uvec4 SampleTextureUInt4(vec2 pos, int type, bool flipY, int mipLevel, float slice) +{ + uvec4 col; + if (type == RESTYPE_TEX1D) + { + int size = textureSize(texUInt1D, mipLevel); + + col = texelFetch(texUInt1D, int(pos.x), mipLevel); + } + else if (type == RESTYPE_TEX1DARRAY) + { + ivec2 size = textureSize(texUInt1DArray, mipLevel); + + col = texelFetch(texUInt1DArray, ivec2(pos.x, slice), mipLevel); + } + else if (type == RESTYPE_TEX2D) + { + ivec2 size = textureSize(texUInt2D, mipLevel); + + if (flipY) + pos.y = size.y - pos.y; + + col = texelFetch(texUInt2D, ivec2(pos), mipLevel); + } + else if (type == RESTYPE_TEX2DARRAY) + { + ivec3 size = textureSize(texUInt2DArray, mipLevel); + + if (flipY) + pos.y = size.y - pos.y; + + col = texelFetch(texUInt2DArray, ivec3(pos, slice), mipLevel); + } + else // if (type == RESTYPE_TEX3D) + { + ivec3 size = textureSize(texUInt3D, mipLevel); + + if (flipY) + pos.y = size.y - pos.y; + + col = texelFetch(texUInt3D, ivec3(pos, slice), mipLevel); + } + + return col; +} + +ivec4 SampleTextureSInt4(vec2 pos, int type, bool flipY, int mipLevel, float slice) +{ + ivec4 col; + if (type == RESTYPE_TEX1D) + { + int size = textureSize(texSInt1D, mipLevel); + + col = texelFetch(texSInt1D, int(pos.x), mipLevel); + } + else if (type == RESTYPE_TEX1DARRAY) + { + ivec2 size = textureSize(texSInt1DArray, mipLevel); + + col = texelFetch(texSInt1DArray, ivec2(pos.x, slice), mipLevel); + } + else if (type == RESTYPE_TEX2D) + { + ivec2 size = textureSize(texSInt2D, mipLevel); + + if (flipY) + pos.y = size.y - pos.y; + + col = texelFetch(texSInt2D, ivec2(pos), mipLevel); + } + else if (type == RESTYPE_TEX2DARRAY) + { + ivec3 size = textureSize(texSInt2DArray, mipLevel); + + if (flipY) + pos.y = size.y - pos.y; + + col = texelFetch(texSInt2DArray, ivec3(pos, slice), mipLevel); + } + else // if (type == RESTYPE_TEX3D) + { + ivec3 size = textureSize(texSInt3D, mipLevel); + + if (flipY) + pos.y = size.y - pos.y; + + col = texelFetch(texSInt3D, ivec3(pos, slice), mipLevel); + } + + return col; +} + + +vec4 SampleTextureFloat4(vec2 pos, int type, bool flipY, bool linearSample, int mipLevel, float slice) +{ + vec4 col; + if (type == RESTYPE_TEX1D) + { + int size = textureSize(tex1D, mipLevel); + + if (linearSample) + col = texture(tex1D, pos.x / size); + else + col = texelFetch(tex1D, int(pos.x), mipLevel); + } + else if (type == RESTYPE_TEX1DARRAY) + { + ivec2 size = textureSize(tex1DArray, mipLevel); + + if (linearSample) + col = texture(tex1DArray, vec2(pos.x / size.x, slice)); + else + col = texelFetch(tex1DArray, ivec2(pos.x, slice), mipLevel); + } + else if (type == RESTYPE_TEX2D) + { + ivec2 size = textureSize(tex2D, mipLevel); + + if (flipY) + pos.y = size.y - pos.y; + + if (linearSample) + col = texture(tex2D, pos / size); + else + col = texelFetch(tex2D, ivec2(pos), mipLevel); + } + else if (type == RESTYPE_TEX2DARRAY) + { + ivec3 size = textureSize(tex2DArray, mipLevel); + + if (flipY) + pos.y = size.y - pos.y; + + if (linearSample) + col = texture(tex2DArray, vec3(pos / size.xy, slice)); + else + col = texelFetch(tex2DArray, ivec3(pos, slice), mipLevel); + } + else if (type == RESTYPE_TEX3D) + { + ivec3 size = textureSize(tex3D, mipLevel); + + if (flipY) + pos.y = size.y - pos.y; + + if (linearSample) + col = texture(tex3D, vec3(pos / size.xy, slice)); + else + col = texelFetch(tex3D, ivec3(pos, slice), mipLevel); + } + else if (type == RESTYPE_TEXCUBE) + { + ivec2 size = textureSize(texCube, mipLevel); + + if (flipY) + pos.y = size.y - pos.y; + + vec3 cubeCoord = CalcCubeCoord(pos / size, int(slice)); + + if (linearSample) + col = texture(texCube, cubeCoord); + else + col = textureLod(texCube, cubeCoord, mipLevel); + } + else // type == RESTYPE_TEXCUBEARRAY + { + ivec3 size = textureSize(texCubeArray, mipLevel); + + if (flipY) + pos.y = size.y - pos.y; + + vec3 cubeCoord = CalcCubeCoord(pos / size.xy, int(slice) % 6); + vec4 arrayCoord = vec4(cubeCoord, int(slice) / 6); + + if (linearSample) + col = texture(texCubeArray, arrayCoord); + else + col = textureLod(texCubeArray, arrayCoord, mipLevel); + } + + return col; +} diff --git a/renderdoc/data/renderdoc.rc b/renderdoc/data/renderdoc.rc index fc74dea7f..c83039634 100644 --- a/renderdoc/data/renderdoc.rc +++ b/renderdoc/data/renderdoc.rc @@ -119,6 +119,8 @@ RESOURCE_mesh_vert TYPE_EMBED "glsl/mesh.vert" RESOURCE_debuguniforms_h TYPE_EMBED "glsl/debuguniforms.h" RESOURCE_text_vert TYPE_EMBED "glsl/text.vert" RESOURCE_text_frag TYPE_EMBED "glsl/text.frag" +RESOURCE_texsample_h TYPE_EMBED "glsl/texsample.h" +RESOURCE_histogram_comp TYPE_EMBED "glsl/histogram.comp" RESOURCE_sourcecodepro_ttf TYPE_EMBED "sourcecodepro.ttf" diff --git a/renderdoc/data/resource.h b/renderdoc/data/resource.h index df9622ad2..7a27e30d1 100644 --- a/renderdoc/data/resource.h +++ b/renderdoc/data/resource.h @@ -21,6 +21,8 @@ #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_sourcecodepro_ttf 301 diff --git a/renderdoc/driver/gl/gl_debug.cpp b/renderdoc/driver/gl/gl_debug.cpp index a2ae67dc4..908ea74dd 100644 --- a/renderdoc/driver/gl/gl_debug.cpp +++ b/renderdoc/driver/gl/gl_debug.cpp @@ -30,6 +30,48 @@ #include "common/string_utils.h" +GLuint GLReplay::CreateCShaderProgram(const char *csSrc) +{ + if(m_pDriver == NULL) return 0; + + MakeCurrentReplayContext(m_DebugCtx); + + WrappedOpenGL &gl = *m_pDriver; + + GLuint cs = gl.glCreateShader(eGL_COMPUTE_SHADER); + + gl.glShaderSource(cs, 1, &csSrc, NULL); + + gl.glCompileShader(cs); + + char buffer[1024]; + GLint status = 0; + + gl.glGetShaderiv(cs, eGL_COMPILE_STATUS, &status); + if(status == 0) + { + gl.glGetShaderInfoLog(cs, 1024, NULL, buffer); + RDCERR("Shader error: %hs", buffer); + } + + GLuint ret = gl.glCreateProgram(); + + gl.glAttachShader(ret, cs); + + gl.glLinkProgram(ret); + + gl.glGetProgramiv(ret, eGL_LINK_STATUS, &status); + if(status == 0) + { + gl.glGetProgramInfoLog(ret, 1024, NULL, buffer); + RDCERR("Link error: %hs", buffer); + } + + gl.glDeleteShader(cs); + + return ret; +} + GLuint GLReplay::CreateShaderProgram(const char *vsSrc, const char *psSrc) { if(m_pDriver == NULL) return 0; @@ -49,20 +91,20 @@ GLuint GLReplay::CreateShaderProgram(const char *vsSrc, const char *psSrc) gl.glCompileShader(vs); gl.glCompileShader(fs); - char buffer[4096]; + char buffer[1024]; GLint status = 0; gl.glGetShaderiv(vs, eGL_COMPILE_STATUS, &status); if(status == 0) { - gl.glGetShaderInfoLog(vs, 4096, NULL, buffer); + gl.glGetShaderInfoLog(vs, 1024, NULL, buffer); RDCERR("Shader error: %hs", buffer); } gl.glGetShaderiv(fs, eGL_COMPILE_STATUS, &status); if(status == 0) { - gl.glGetShaderInfoLog(fs, 4096, NULL, buffer); + gl.glGetShaderInfoLog(fs, 1024, NULL, buffer); RDCERR("Shader error: %hs", buffer); } @@ -89,6 +131,8 @@ void GLReplay::InitDebugData() uint64_t id = MakeOutputWindow(NULL, true); m_DebugCtx = &m_OutputWindows[id]; + + MakeCurrentReplayContext(m_DebugCtx); } DebugData.outWidth = 0.0f; DebugData.outHeight = 0.0f; @@ -99,6 +143,7 @@ void GLReplay::InitDebugData() DebugData.blitProg = CreateShaderProgram(DebugData.blitvsSource.c_str(), DebugData.blitfsSource.c_str()); string texfs = GetEmbeddedResource(debuguniforms_h); + texfs += GetEmbeddedResource(texsample_h); texfs += GetEmbeddedResource(texdisplay_frag); DebugData.texDisplayProg = CreateShaderProgram(DebugData.blitvsSource.c_str(), texfs.c_str()); @@ -153,7 +198,10 @@ void GLReplay::InitDebugData() for(size_t i=0; i < ARRAY_COUNT(DebugData.UBOs); i++) { gl.glBindBuffer(eGL_UNIFORM_BUFFER, DebugData.UBOs[i]); - gl.glBufferData(eGL_UNIFORM_BUFFER, sizeof(texdisplay), NULL, eGL_DYNAMIC_DRAW); + gl.glBufferData(eGL_UNIFORM_BUFFER, 512, NULL, eGL_DYNAMIC_DRAW); + RDCCOMPILE_ASSERT(sizeof(texdisplay) < 512, "texdisplay UBO too large"); + RDCCOMPILE_ASSERT(sizeof(FontUniforms) < 512, "texdisplay UBO too large"); + RDCCOMPILE_ASSERT(sizeof(HistogramCBufferData) < 512, "texdisplay UBO too large"); } DebugData.overlayTexWidth = DebugData.overlayTexHeight = 0; @@ -174,6 +222,64 @@ void GLReplay::InitDebugData() gl.glGenVertexArrays(1, &DebugData.emptyVAO); gl.glBindVertexArray(DebugData.emptyVAO); + + // histogram/minmax data + { + string glslheader = GetEmbeddedResource(debuguniforms_h); + + string histogramglsl = GetEmbeddedResource(texsample_h); + histogramglsl += GetEmbeddedResource(histogram_comp); + + RDCEraseEl(DebugData.minmaxTileProgram); + RDCEraseEl(DebugData.histogramProgram); + RDCEraseEl(DebugData.minmaxResultProgram); + + for(int t=1; t <= TEXDISPLAY_TYPEMASK; t++) + { + // float, uint, sint + for(int i=0; i < 3; i++) + { + int idx = t; + if(i == 1) idx |= TEXDISPLAY_UINT_TEX; + if(i == 2) idx |= TEXDISPLAY_SINT_TEX; + + { + string glsl = glslheader; + glsl += string("#define SHADER_RESTYPE ") + ToStr::Get(t) + "\n"; + glsl += string("#define UINT_TEX ") + (i == 1 ? "1" : "0") + "\n"; + glsl += string("#define SINT_TEX ") + (i == 2 ? "1" : "0") + "\n"; + glsl += string("#define RENDERDOC_TileMinMaxCS 1\n"); + glsl += histogramglsl; + + DebugData.minmaxTileProgram[idx] = CreateCShaderProgram(glsl.c_str()); + } + + if(t == 1) + { + string glsl = glslheader; + glsl += string("#define SHADER_RESTYPE ") + ToStr::Get(t) + "\n"; + glsl += string("#define UINT_TEX ") + (i == 1 ? "1" : "0") + "\n"; + glsl += string("#define SINT_TEX ") + (i == 2 ? "1" : "0") + "\n"; + glsl += string("#define RENDERDOC_ResultMinMaxCS 1\n"); + glsl += histogramglsl; + + DebugData.minmaxResultProgram[i] = CreateCShaderProgram(glsl.c_str()); + } + } + } + + gl.glGenBuffers(1, &DebugData.minmaxTileResult); + gl.glGenBuffers(1, &DebugData.minmaxResult); + + 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; + + gl.glNamedBufferStorageEXT(DebugData.minmaxTileResult, byteSize, NULL, 0); + gl.glNamedBufferStorageEXT(DebugData.minmaxResult, sizeof(Vec4f)*2, NULL, GL_MAP_READ_BIT); + } MakeCurrentReplayContext(&m_ReplayCtx); @@ -181,6 +287,122 @@ void GLReplay::InitDebugData() gl.glBindVertexArray(DebugData.meshVAO); } +bool GLReplay::GetMinMax(ResourceId texid, uint32_t sliceFace, uint32_t mip, uint32_t sample, float *minval, float *maxval) +{ + if(m_pDriver->m_Textures.find(texid) == m_pDriver->m_Textures.end()) + return false; + + auto &texDetails = m_pDriver->m_Textures[texid]; + + FetchTexture details = GetTexture(texid); + + const GLHookSet &gl = m_pDriver->GetHookset(); + + gl.glBindBufferBase(eGL_UNIFORM_BUFFER, 0, DebugData.UBOs[0]); + HistogramCBufferData *cdata = (HistogramCBufferData *)gl.glMapBufferRange(eGL_UNIFORM_BUFFER, 0, sizeof(HistogramCBufferData), + GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT); + + cdata->HistogramTextureResolution.x = (float)RDCMAX(details.width>>mip, 1U); + cdata->HistogramTextureResolution.y = (float)RDCMAX(details.height>>mip, 1U); + cdata->HistogramTextureResolution.z = (float)RDCMAX(details.depth>>mip, 1U); + cdata->HistogramSlice = (float)sliceFace; + cdata->HistogramMip = (int)mip; + cdata->HistogramSample = (int)RDCCLAMP(sample, 0U, details.msSamp-1); + if(sample == ~0U) cdata->HistogramSample = -int(details.msSamp); + cdata->HistogramMin = 0.0f; + cdata->HistogramMax = 1.0f; + cdata->HistogramChannels = 0xf; + + int texSlot = 0; + int intIdx = 0; + + switch (texDetails.curType) + { + case eGL_TEXTURE_1D: + texSlot = RESTYPE_TEX1D; + break; + default: + RDCWARN("Unexpected texture type"); + case eGL_TEXTURE_2D: + texSlot = RESTYPE_TEX2D; + break; + case eGL_TEXTURE_3D: + texSlot = RESTYPE_TEX3D; + break; + case eGL_TEXTURE_CUBE_MAP: + texSlot = RESTYPE_TEXCUBE; + break; + case eGL_TEXTURE_1D_ARRAY: + texSlot = RESTYPE_TEX1DARRAY; + break; + case eGL_TEXTURE_2D_ARRAY: + texSlot = RESTYPE_TEX2DARRAY; + break; + case eGL_TEXTURE_CUBE_MAP_ARRAY: + texSlot = RESTYPE_TEXCUBEARRAY; + break; + } + + if(details.format.compType == eCompType_UInt) + { + texSlot |= TEXDISPLAY_UINT_TEX; + intIdx = 1; + } + if(details.format.compType == eCompType_SInt) + { + texSlot |= TEXDISPLAY_SINT_TEX; + intIdx = 2; + } + + if(details.dimension == 3) + cdata->HistogramSlice = float(sliceFace)/float(details.depth); + + int blocksX = (int)ceil(cdata->HistogramTextureResolution.x/float(HGRAM_PIXELS_PER_TILE*HGRAM_TILES_PER_BLOCK)); + int blocksY = (int)ceil(cdata->HistogramTextureResolution.y/float(HGRAM_PIXELS_PER_TILE*HGRAM_TILES_PER_BLOCK)); + + gl.glUnmapBuffer(eGL_UNIFORM_BUFFER); + + gl.glActiveTexture((RDCGLenum)(eGL_TEXTURE0 + texSlot)); + gl.glBindTexture(texDetails.curType, texDetails.resource.name); + gl.glBindSampler(texSlot, DebugData.pointSampler); + + gl.glBindBufferBase(eGL_SHADER_STORAGE_BUFFER, 0, DebugData.minmaxTileResult); + + gl.glUseProgram(DebugData.minmaxTileProgram[texSlot]); + gl.glDispatchCompute(blocksX, blocksY, 1); + + gl.glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT); + + gl.glBindBufferBase(eGL_SHADER_STORAGE_BUFFER, 0, DebugData.minmaxResult); + gl.glBindBufferBase(eGL_SHADER_STORAGE_BUFFER, 1, DebugData.minmaxTileResult); + + gl.glUseProgram(DebugData.minmaxResultProgram[intIdx]); + gl.glDispatchCompute(1, 1, 1); + + gl.glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT); + + Vec4f minmax[2]; + gl.glBindBuffer(eGL_COPY_READ_BUFFER, DebugData.minmaxResult); + gl.glGetBufferSubData(eGL_COPY_READ_BUFFER, 0, sizeof(minmax), minmax); + + 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; + + return true; +} + +bool GLReplay::GetHistogram(ResourceId texid, uint32_t sliceFace, uint32_t mip, uint32_t sample, float minval, float maxval, bool channels[4], vector &histogram) +{ + return true; +} + void GLReplay::PickPixel(ResourceId texture, uint32_t x, uint32_t y, uint32_t sliceFace, uint32_t mip, uint32_t sample, float pixel[4]) { WrappedOpenGL &gl = *m_pDriver; @@ -236,29 +458,29 @@ bool GLReplay::RenderTexture(TextureDisplay cfg) int resType; switch (texDetails.curType) { - case eGL_TEXTURE_1D: - resType = RESTYPE_TEX1D; - break; - default: - RDCWARN("Unexpected texture type"); - case eGL_TEXTURE_2D: - resType = RESTYPE_TEX2D; - break; - case eGL_TEXTURE_3D: - resType = RESTYPE_TEX3D; - break; - case eGL_TEXTURE_CUBE_MAP: - resType = RESTYPE_TEXCUBE; - break; - case eGL_TEXTURE_1D_ARRAY: - resType = RESTYPE_TEX1DARRAY; - break; - case eGL_TEXTURE_2D_ARRAY: - resType = RESTYPE_TEX2DARRAY; - break; - case eGL_TEXTURE_CUBE_MAP_ARRAY: - resType = RESTYPE_TEXCUBEARRAY; - break; + case eGL_TEXTURE_1D: + resType = RESTYPE_TEX1D; + break; + default: + RDCWARN("Unexpected texture type"); + case eGL_TEXTURE_2D: + resType = RESTYPE_TEX2D; + break; + case eGL_TEXTURE_3D: + resType = RESTYPE_TEX3D; + break; + case eGL_TEXTURE_CUBE_MAP: + resType = RESTYPE_TEXCUBE; + break; + case eGL_TEXTURE_1D_ARRAY: + resType = RESTYPE_TEX1DARRAY; + break; + case eGL_TEXTURE_2D_ARRAY: + resType = RESTYPE_TEX2DARRAY; + break; + case eGL_TEXTURE_CUBE_MAP_ARRAY: + resType = RESTYPE_TEXCUBEARRAY; + break; } RDCGLenum dsTexMode = eGL_NONE; diff --git a/renderdoc/driver/gl/gl_replay.cpp b/renderdoc/driver/gl/gl_replay.cpp index 39910ad6c..6432f6ec6 100644 --- a/renderdoc/driver/gl/gl_replay.cpp +++ b/renderdoc/driver/gl/gl_replay.cpp @@ -95,7 +95,10 @@ vector GLReplay::GetTextures() vector ret; for(auto it=m_pDriver->m_Textures.begin(); it != m_pDriver->m_Textures.end(); ++it) + { ret.push_back(it->first); + CacheTexture(it->first); + } return ret; } @@ -309,7 +312,7 @@ bool GLReplay::IsRenderOutput(ResourceId id) return false; } -FetchTexture GLReplay::GetTexture(ResourceId id) +void GLReplay::CacheTexture(ResourceId id) { FetchTexture tex; @@ -321,7 +324,7 @@ FetchTexture GLReplay::GetTexture(ResourceId id) { RDCERR("Details for invalid texture id %llu requested", id); RDCEraseEl(tex); - return tex; + return; } WrappedOpenGL &gl = *m_pDriver; @@ -478,7 +481,7 @@ FetchTexture GLReplay::GetTexture(ResourceId id) } } - return tex; + m_CachedTextures[id] = tex; } FetchBuffer GLReplay::GetBuffer(ResourceId id) @@ -1425,18 +1428,6 @@ void GLReplay::FillCBufferVariables(ResourceId shader, uint32_t cbufSlot, vector #pragma endregion -bool GLReplay::GetMinMax(ResourceId texid, uint32_t sliceFace, uint32_t mip, uint32_t sample, float *minval, float *maxval) -{ - RDCUNIMPLEMENTED("GetMinMax"); - return false; -} - -bool GLReplay::GetHistogram(ResourceId texid, uint32_t sliceFace, uint32_t mip, uint32_t sample, float minval, float maxval, bool channels[4], vector &histogram) -{ - RDCUNIMPLEMENTED("GetHistogram"); - return false; -} - void GLReplay::InitPostVSBuffers(uint32_t frameID, uint32_t eventID) { GLNOTIMP("GLReplay::InitPostVSBuffers"); diff --git a/renderdoc/driver/gl/gl_replay.h b/renderdoc/driver/gl/gl_replay.h index 8e9fee97b..d3b4b04aa 100644 --- a/renderdoc/driver/gl/gl_replay.h +++ b/renderdoc/driver/gl/gl_replay.h @@ -50,7 +50,7 @@ class GLReplay : public IReplayDriver FetchBuffer GetBuffer(ResourceId id); vector GetTextures(); - FetchTexture GetTexture(ResourceId id); + FetchTexture GetTexture(ResourceId id) { return m_CachedTextures[id]; } ShaderReflection *GetShader(ResourceId id); @@ -175,6 +175,12 @@ class GLReplay : public IReplayDriver string genericvsSource; string genericfsSource; + // min/max data + GLuint minmaxTileResult; // tile result buffer + GLuint minmaxResult; // Vec4f[2] final result buffer + GLuint minmaxResultProgram[3]; // float/uint/sint tile result -> final result program + GLuint minmaxTileProgram[32]; // RESTYPE indexed (see debuguniforms.h, 1d/2d/3d etc | uint/sint) src tex -> tile result buf program + // program that does a blit of texture from input to output, // no transformation or scaling GLuint blitProg; @@ -209,6 +215,7 @@ class GLReplay : public IReplayDriver void InitDebugData(); GLuint CreateShaderProgram(const char *vs, const char *ps); + GLuint CreateCShaderProgram(const char *cs); void InitOutputWindow(OutputWindow &outwin); void CreateOutputWindowBackbuffer(OutputWindow &outwin); @@ -224,6 +231,10 @@ class GLReplay : public IReplayDriver map m_OutputWindows; bool m_Proxy; + + void CacheTexture(ResourceId id); + + map m_CachedTextures; WrappedOpenGL *m_pDriver; diff --git a/renderdoc/renderdoc.vcxproj b/renderdoc/renderdoc.vcxproj index 6ca150aca..a567b6812 100644 --- a/renderdoc/renderdoc.vcxproj +++ b/renderdoc/renderdoc.vcxproj @@ -249,6 +249,7 @@ + @@ -376,6 +377,7 @@ + @@ -390,4 +392,4 @@ - + \ No newline at end of file diff --git a/renderdoc/renderdoc.vcxproj.filters b/renderdoc/renderdoc.vcxproj.filters index e190f6878..680065c02 100644 --- a/renderdoc/renderdoc.vcxproj.filters +++ b/renderdoc/renderdoc.vcxproj.filters @@ -303,6 +303,9 @@ 3rdparty\stb + + Resources\glsl + @@ -565,6 +568,9 @@ Resources\glsl + + Resources\glsl +