mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-05-24 02:40:52 +00:00
Implement min/max calculation for OpenGL
* Same implementation as D3D11 essentially * Split out the texture sampling from texdisplay.frag into its own file so it can be reused. Also removed the discard;s from the texture sample functions and moved them up into the texture display function.
This commit is contained in:
+20
-15
@@ -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))
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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"
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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<uint32_t> &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;
|
||||
|
||||
@@ -95,7 +95,10 @@ vector<ResourceId> GLReplay::GetTextures()
|
||||
vector<ResourceId> 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<uint32_t> &histogram)
|
||||
{
|
||||
RDCUNIMPLEMENTED("GetHistogram");
|
||||
return false;
|
||||
}
|
||||
|
||||
void GLReplay::InitPostVSBuffers(uint32_t frameID, uint32_t eventID)
|
||||
{
|
||||
GLNOTIMP("GLReplay::InitPostVSBuffers");
|
||||
|
||||
@@ -50,7 +50,7 @@ class GLReplay : public IReplayDriver
|
||||
FetchBuffer GetBuffer(ResourceId id);
|
||||
|
||||
vector<ResourceId> 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<uint64_t, OutputWindow> m_OutputWindows;
|
||||
|
||||
bool m_Proxy;
|
||||
|
||||
void CacheTexture(ResourceId id);
|
||||
|
||||
map<ResourceId, FetchTexture> m_CachedTextures;
|
||||
|
||||
WrappedOpenGL *m_pDriver;
|
||||
|
||||
|
||||
@@ -249,6 +249,7 @@
|
||||
<ClInclude Include="core\resource_manager.h" />
|
||||
<ClInclude Include="core\socket_helpers.h" />
|
||||
<ClInclude Include="data\glsl\debuguniforms.h" />
|
||||
<ClInclude Include="data\glsl\texsample.h" />
|
||||
<ClInclude Include="data\hlsl\debugcbuffers.h" />
|
||||
<ClInclude Include="data\resource.h" />
|
||||
<ClInclude Include="data\version.h" />
|
||||
@@ -376,6 +377,7 @@
|
||||
<None Include="data\glsl\checkerboard.frag" />
|
||||
<None Include="data\glsl\generic.frag" />
|
||||
<None Include="data\glsl\generic.vert" />
|
||||
<None Include="data\glsl\histogram.comp" />
|
||||
<None Include="data\glsl\mesh.vert" />
|
||||
<None Include="data\glsl\texdisplay.frag" />
|
||||
<None Include="data\glsl\text.frag" />
|
||||
@@ -390,4 +392,4 @@
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
@@ -303,6 +303,9 @@
|
||||
<ClInclude Include="3rdparty\stb\stb_truetype.h">
|
||||
<Filter>3rdparty\stb</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="data\glsl\texsample.h">
|
||||
<Filter>Resources\glsl</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="maths\camera.cpp">
|
||||
@@ -565,6 +568,9 @@
|
||||
<None Include="data\glsl\text.vert">
|
||||
<Filter>Resources\glsl</Filter>
|
||||
</None>
|
||||
<None Include="data\glsl\histogram.comp">
|
||||
<Filter>Resources\glsl</Filter>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="data\renderdoc.rc">
|
||||
|
||||
Reference in New Issue
Block a user