Add visualization of most missing OpenGL texture types (cube maps, texture arrays, stencil, 1D/3D textures, integer textures), take selected mip level into account and point sampling when required.

This commit is contained in:
valeriog
2014-10-31 19:47:42 +01:00
parent d18557239f
commit baa530eb5f
8 changed files with 466 additions and 71 deletions
+84
View File
@@ -0,0 +1,84 @@
/******************************************************************************
* The MIT License (MIT)
*
* Copyright (c) 2014 Crytek
*
* 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.
******************************************************************************/
// use some preprocessor hacks to compile the same header in both GLSL and C++ so we can define
// classes that represent a whole cbuffer
#if defined(__cplusplus)
#define uniform struct
#define vec2 Vec2f
#define vec3 Vec3f
#define vec4 Vec4f
#define BINDING(b)
#else
#version 420 core
#define BINDING(b) layout (binding = b, std140)
#endif
BINDING(0) uniform texdisplay
{
vec2 Position;
float Scale;
float HDRMul;
vec4 Channels;
float RangeMinimum;
float InverseRangeSize;
float MipLevel;
int FlipY;
vec3 TextureResolutionPS;
int OutputDisplayFormat;
vec2 OutputRes;
int RawOutput;
float Slice;
};
// some constants available to both C++ and GLSL for configuring display
#define CUBEMAP_FACE_POS_X 0
#define CUBEMAP_FACE_NEG_X 1
#define CUBEMAP_FACE_POS_Y 2
#define CUBEMAP_FACE_NEG_Y 3
#define CUBEMAP_FACE_POS_Z 4
#define CUBEMAP_FACE_NEG_Z 5
#define RESTYPE_TEX1D 0x1
#define RESTYPE_TEX2D 0x2
#define RESTYPE_TEX3D 0x3
#define RESTYPE_TEXCUBE 0x4
#define RESTYPE_TEX1DARRAY 0x5
#define RESTYPE_TEX2DARRAY 0x6
#define RESTYPE_TEXCUBEARRAY 0x7
#define TEXDISPLAY_TYPEMASK 0x7
#define TEXDISPLAY_UINT_TEX 0x8
#define TEXDISPLAY_SINT_TEX 0x10
+260 -33
View File
@@ -22,52 +22,269 @@
* THE SOFTWARE.
******************************************************************************/
#version 420 core
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 = 0, std140) uniform texdisplay
{
vec2 Position;
float Scale;
float HDRMul;
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;
vec4 Channels;
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;
float RangeMinimum;
float InverseRangeSize;
float MipLevel;
int FlipY;
vec3 TextureResolutionPS;
int OutputDisplayFormat;
vec2 OutputRes;
int RawOutput;
float Slice;
};
layout (binding = 0) uniform sampler2D tex0;
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;
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;
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;
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;
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;
bool sintTex = (OutputDisplayFormat & TEXDISPLAY_SINT_TEX) != 0;
vec4 col;
uvec4 ucol;
ivec4 scol;
// calc screen co-ords with origin top left, modified by Position
vec2 scr = vec2(gl_FragCoord.x, OutputRes.y - gl_FragCoord.y) - Position.xy;
// calc UVs in texture
vec2 uv = scr/(textureSize(tex0,0)*Scale);
// discard if we're rendering outside input texture
if(uv.x < 0 || uv.y < 0 || uv.x > 1 || uv.y > 1) discard;
// sample the texture.
// TODO: handle uint/sint/float textures (OutputDisplayFormat).
// TODO: Use MipLevel and Slice parameters
// TODO: Sample from a point or linear sampler depending on if we're
// upscaling (point) or downscaling mip 0 (linear)
vec4 col = texture(tex0, vec2(uv.x, FlipY > 0 ? uv.y : 1.0f-uv.y));
if (uintTex)
{
ucol = SampleTextureUInt4(scr / Scale, OutputDisplayFormat & TEXDISPLAY_TYPEMASK, FlipY == 0, int(MipLevel), Slice);
}
else if (sintTex)
{
scol = SampleTextureSInt4(scr / Scale, OutputDisplayFormat & TEXDISPLAY_TYPEMASK, FlipY == 0, int(MipLevel), Slice);
}
else
{
col = SampleTextureFloat4(scr / Scale, OutputDisplayFormat & TEXDISPLAY_TYPEMASK, FlipY == 0, (Scale < 1.0 && MipLevel == 0.0), int(MipLevel), Slice);
}
if(RawOutput != 0)
{
if (uintTex)
color_out = uintBitsToFloat(ucol);
else if (sintTex)
color_out = intBitsToFloat(scol);
else
color_out = col;
return;
}
@@ -75,9 +292,19 @@ void main(void)
// RGBM encoding
if(HDRMul > 0.0f)
{
col = vec4(col.rgb * col.a * HDRMul, 1.0f);
if (uintTex)
col = vec4(ucol.rgb * ucol.a * uint(HDRMul), 1.0);
else if (sintTex)
col = vec4(scol.rgb * scol.a * int(HDRMul), 1.0);
else
col = vec4(col.rgb * col.a * HDRMul, 1.0);
}
if (uintTex)
col = vec4(ucol);
else if (sintTex)
col = vec4(scol);
col = ((col - RangeMinimum)*InverseRangeSize);
col = mix(vec4(0,0,0,1), col, Channels);
+1
View File
@@ -116,6 +116,7 @@ RESOURCE_checkerboard_frag TYPE_EMBED "glsl/checkerboard.frag"
RESOURCE_generic_vert TYPE_EMBED "glsl/generic.vert"
RESOURCE_generic_frag TYPE_EMBED "glsl/generic.frag"
RESOURCE_mesh_vert TYPE_EMBED "glsl/mesh.vert"
RESOURCE_debuguniforms_h TYPE_EMBED "glsl/debuguniforms.h"
RESOURCE_sourcecodepro_ttf TYPE_EMBED "sourcecodepro.ttf"
+1
View File
@@ -18,6 +18,7 @@
#define RESOURCE_generic_vert 205
#define RESOURCE_generic_frag 206
#define RESOURCE_mesh_vert 207
#define RESOURCE_debuguniforms_h 208
#define RESOURCE_sourcecodepro_ttf 301
+116 -36
View File
@@ -79,6 +79,8 @@ GLuint GLReplay::CreateShaderProgram(const char *vsSrc, const char *psSrc)
return ret;
}
#include "data/glsl/debuguniforms.h"
void GLReplay::InitDebugData()
{
if(m_pDriver == NULL) return;
@@ -96,7 +98,8 @@ void GLReplay::InitDebugData()
DebugData.blitProg = CreateShaderProgram(DebugData.blitvsSource.c_str(), DebugData.blitfsSource.c_str());
string texfs = GetEmbeddedResource(texdisplay_frag);
string texfs = GetEmbeddedResource(debuguniforms_h);
texfs += GetEmbeddedResource(texdisplay_frag);
DebugData.texDisplayProg = CreateShaderProgram(DebugData.blitvsSource.c_str(), texfs.c_str());
@@ -150,7 +153,7 @@ 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, Debug_UBOSize, NULL, eGL_DYNAMIC_DRAW);
gl.glBufferData(eGL_UNIFORM_BUFFER, sizeof(texdisplay), NULL, eGL_DYNAMIC_DRAW);
}
DebugData.overlayTexWidth = DebugData.overlayTexHeight = 0;
@@ -220,6 +223,8 @@ void GLReplay::PickPixel(ResourceId texture, uint32_t x, uint32_t y, uint32_t sl
bool GLReplay::RenderTexture(TextureDisplay cfg)
{
FetchTexture tex = GetTexture(cfg.texid);
MakeCurrentReplayContext(m_DebugCtx);
WrappedOpenGL &gl = *m_pDriver;
@@ -228,42 +233,102 @@ bool GLReplay::RenderTexture(TextureDisplay cfg)
auto &texDetails = m_pDriver->m_Textures[cfg.texid];
gl.glActiveTexture(eGL_TEXTURE0);
gl.glBindTexture(eGL_TEXTURE_2D, texDetails.resource.name);
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;
}
if(cfg.mip == 0 && cfg.scale < 1.0f)
gl.glBindSampler(0, DebugData.linearSampler);
RDCGLenum dsTexMode = eGL_NONE;
if (tex.creationFlags & eTextureCreate_DSV)
{
if (cfg.Green)
{
dsTexMode = eGL_STENCIL_INDEX;
// Stencil texture sampling is not normalized in OpenGL
resType |= TEXDISPLAY_UINT_TEX;
float rangeScale;
switch (tex.format.rawType)
{
case eGL_STENCIL_INDEX1:
rangeScale = 1.0f;
break;
case eGL_STENCIL_INDEX4:
rangeScale = 16.0f;
break;
default:
RDCWARN("Unexpected raw format for stencil visualization");
case eGL_DEPTH24_STENCIL8:
case eGL_DEPTH32F_STENCIL8:
case eGL_STENCIL_INDEX8:
rangeScale = 256.0f;
break;
case eGL_STENCIL_INDEX16:
rangeScale = 65536.0f;
break;
}
cfg.rangemin *= rangeScale;
cfg.rangemax *= rangeScale;
}
else
dsTexMode = eGL_DEPTH_COMPONENT;
}
else
gl.glBindSampler(0, DebugData.pointSampler);
{
switch (tex.format.compType)
{
case eCompType_UInt:
resType |= TEXDISPLAY_UINT_TEX;
break;
case eCompType_SNorm:
resType |= TEXDISPLAY_SINT_TEX;
break;
}
}
gl.glActiveTexture((RDCGLenum)(eGL_TEXTURE0 + resType));
gl.glBindTexture(texDetails.curType, texDetails.resource.name);
GLint origDSTexMode = eGL_DEPTH_COMPONENT;
if (dsTexMode != eGL_NONE)
{
gl.glGetTexParameteriv(texDetails.curType, eGL_DEPTH_STENCIL_TEXTURE_MODE, &origDSTexMode);
gl.glTexParameteri(texDetails.curType, eGL_DEPTH_STENCIL_TEXTURE_MODE, dsTexMode);
}
if(cfg.mip == 0 && cfg.scale < 1.0f && dsTexMode == eGL_NONE)
gl.glBindSampler(resType, DebugData.linearSampler);
else
gl.glBindSampler(resType, DebugData.pointSampler);
GLint tex_x = texDetails.width, tex_y = texDetails.height, tex_z = texDetails.depth;
gl.glBindBufferBase(eGL_UNIFORM_BUFFER, 0, DebugData.UBOs[0]);
struct uboData
{
Vec2f Position;
float Scale;
float HDRMul;
Vec4f Channels;
float RangeMinimum;
float InverseRangeSize;
float MipLevel;
int32_t FlipY;
Vec3f TextureResolutionPS;
int32_t OutputDisplayFormat;
Vec2f OutputRes;
int32_t RawOutput;
float Slice;
};
uboData *ubo = (uboData *)gl.glMapBufferRange(eGL_UNIFORM_BUFFER, 0, sizeof(uboData), GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT);
RDCCOMPILE_ASSERT(sizeof(uboData) <= Debug_UBOSize, "UBO data is too big");
texdisplay *ubo = (texdisplay *)gl.glMapBufferRange(eGL_UNIFORM_BUFFER, 0, sizeof(texdisplay), GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT);
float x = cfg.offx;
float y = cfg.offy;
@@ -297,17 +362,29 @@ bool GLReplay::RenderTexture(TextureDisplay cfg)
if(cfg.rangemax <= cfg.rangemin) cfg.rangemax += 0.00001f;
ubo->Channels.x = cfg.Red ? 1.0f : 0.0f;
ubo->Channels.y = cfg.Green ? 1.0f : 0.0f;
ubo->Channels.z = cfg.Blue ? 1.0f : 0.0f;
ubo->Channels.w = cfg.Alpha ? 1.0f : 0.0f;
if (dsTexMode == eGL_NONE)
{
ubo->Channels.x = cfg.Red ? 1.0f : 0.0f;
ubo->Channels.y = cfg.Green ? 1.0f : 0.0f;
ubo->Channels.z = cfg.Blue ? 1.0f : 0.0f;
ubo->Channels.w = cfg.Alpha ? 1.0f : 0.0f;
}
else
{
// Both depth and stencil texture mode use the red channel
ubo->Channels.x = 1.0f;
ubo->Channels.y = 0.0f;
ubo->Channels.z = 0.0f;
ubo->Channels.w = 0.0f;
}
ubo->RangeMinimum = cfg.rangemin;
ubo->InverseRangeSize = 1.0f/(cfg.rangemax-cfg.rangemin);
ubo->MipLevel = (float)cfg.mip;
ubo->Slice = (float)cfg.sliceFace;
ubo->OutputDisplayFormat = 0x2; // 2d. Unused for now
ubo->OutputDisplayFormat = resType;
ubo->RawOutput = cfg.rawoutput ? 1 : 0;
@@ -335,6 +412,9 @@ bool GLReplay::RenderTexture(TextureDisplay cfg)
gl.glBindSampler(0, 0);
if (dsTexMode != eGL_NONE)
gl.glTexParameteri(texDetails.curType, eGL_DEPTH_STENCIL_TEXTURE_MODE, origDSTexMode);
return true;
}
-2
View File
@@ -205,8 +205,6 @@ class GLReplay : public IReplayDriver
GLuint emptyVAO;
} DebugData;
static const size_t Debug_UBOSize = 64 * sizeof(Vec4f);
void InitDebugData();
+1
View File
@@ -248,6 +248,7 @@
<ClInclude Include="core\replay_proxy.h" />
<ClInclude Include="core\resource_manager.h" />
<ClInclude Include="core\socket_helpers.h" />
<ClInclude Include="data\glsl\debuguniforms.h" />
<ClInclude Include="data\hlsl\debugcbuffers.h" />
<ClInclude Include="data\resource.h" />
<ClInclude Include="data\version.h" />
+3
View File
@@ -240,6 +240,9 @@
<ClInclude Include="data\hlsl\debugcbuffers.h">
<Filter>Resources\hlsl</Filter>
</ClInclude>
<ClInclude Include="data\glsl\debuguniforms.h">
<Filter>Resources\glsl</Filter>
</ClInclude>
<ClInclude Include="driver\gl\gl_renderstate.h">
<Filter>Drivers\OpenGL</Filter>
</ClInclude>