Commit 83a369bb by James Dong Committed by Commit Bot

Vulkan: Improve cubemap emulation seam handling

Changes seamful cubemap emulation to always compute the derivative, emulating the bias parameter by scaling the provided derivatives. This results in more accurate mipmap levels for seams within primitives. There are some artifacts as a result of how derivatives are calculated, but this matches the native driver. Bug: angleproject:3243 Bug: angleproject:3732 Change-Id: Icb976e2a7e14cb4210645571edc037d4e607bd0d Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1754383 Commit-Queue: James Dong <dongja@google.com> Reviewed-by: 's avatarShahbaz Youssefi <syoussefi@chromium.org>
parent 2f4a7518
...@@ -290,12 +290,7 @@ const ShCompileOptions SH_EMULATE_GL_BASE_VERTEX_BASE_INSTANCE = UINT64_C(1) << ...@@ -290,12 +290,7 @@ const ShCompileOptions SH_EMULATE_GL_BASE_VERTEX_BASE_INSTANCE = UINT64_C(1) <<
// Emulate seamful cube map sampling for OpenGL ES2.0. Currently only applies to the Vulkan // Emulate seamful cube map sampling for OpenGL ES2.0. Currently only applies to the Vulkan
// backend, as is done after samplers are moved out of structs. Can likely be made to work on // backend, as is done after samplers are moved out of structs. Can likely be made to work on
// the other backends as well. // the other backends as well.
//
// There are two variations of this. One using subgroup operations where available, and another
// that emulates those operations using dFdxFine and dFdyFine. The latter is more universally
// available, but is buggy on Nvidia.
const ShCompileOptions SH_EMULATE_SEAMFUL_CUBE_MAP_SAMPLING = UINT64_C(1) << 44; const ShCompileOptions SH_EMULATE_SEAMFUL_CUBE_MAP_SAMPLING = UINT64_C(1) << 44;
const ShCompileOptions SH_EMULATE_SEAMFUL_CUBE_MAP_SAMPLING_WITH_SUBGROUP_OP = UINT64_C(1) << 45;
// If requested, validates the AST after every transformation. Useful for debugging. // If requested, validates the AST after every transformation. Useful for debugging.
const ShCompileOptions SH_VALIDATE_AST = UINT64_C(1) << 46; const ShCompileOptions SH_VALIDATE_AST = UINT64_C(1) << 46;
......
...@@ -665,11 +665,6 @@ bool TranslatorVulkan::translate(TIntermBlock *root, ...@@ -665,11 +665,6 @@ bool TranslatorVulkan::translate(TIntermBlock *root,
sink << "#version 450 core\n"; sink << "#version 450 core\n";
if (compileOptions & SH_EMULATE_SEAMFUL_CUBE_MAP_SAMPLING_WITH_SUBGROUP_OP)
{
sink << "#extension GL_KHR_shader_subgroup_quad : require\n";
}
// Write out default uniforms into a uniform block assigned to a specific set/binding. // Write out default uniforms into a uniform block assigned to a specific set/binding.
int defaultUniformCount = 0; int defaultUniformCount = 0;
int aggregateTypesUsedForUniforms = 0; int aggregateTypesUsedForUniforms = 0;
...@@ -732,12 +727,10 @@ bool TranslatorVulkan::translate(TIntermBlock *root, ...@@ -732,12 +727,10 @@ bool TranslatorVulkan::translate(TIntermBlock *root,
// Rewrite samplerCubes as sampler2DArrays. This must be done after rewriting struct samplers // Rewrite samplerCubes as sampler2DArrays. This must be done after rewriting struct samplers
// as it doesn't expect that. // as it doesn't expect that.
if (compileOptions & (SH_EMULATE_SEAMFUL_CUBE_MAP_SAMPLING | if (compileOptions & SH_EMULATE_SEAMFUL_CUBE_MAP_SAMPLING)
SH_EMULATE_SEAMFUL_CUBE_MAP_SAMPLING_WITH_SUBGROUP_OP))
{ {
if (!RewriteCubeMapSamplersAs2DArray( if (!RewriteCubeMapSamplersAs2DArray(this, root, &getSymbolTable(),
this, root, &getSymbolTable(), getShaderType() == GL_FRAGMENT_SHADER, getShaderType() == GL_FRAGMENT_SHADER))
compileOptions & SH_EMULATE_SEAMFUL_CUBE_MAP_SAMPLING_WITH_SUBGROUP_OP))
{ {
return false; return false;
} }
......
...@@ -23,8 +23,7 @@ class TSymbolTable; ...@@ -23,8 +23,7 @@ class TSymbolTable;
ANGLE_NO_DISCARD bool RewriteCubeMapSamplersAs2DArray(TCompiler *compiler, ANGLE_NO_DISCARD bool RewriteCubeMapSamplersAs2DArray(TCompiler *compiler,
TIntermBlock *root, TIntermBlock *root,
TSymbolTable *symbolTable, TSymbolTable *symbolTable,
bool isFragmentShader, bool isFragmentShader);
bool useSubgroupOps);
} // namespace sh } // namespace sh
#endif // COMPILER_TRANSLATOR_TREEOPS_REWRITECUBEMAPSAMPLERSAS2DARRAY_H_ #endif // COMPILER_TRANSLATOR_TREEOPS_REWRITECUBEMAPSAMPLERSAS2DARRAY_H_
...@@ -239,7 +239,6 @@ ContextVk::ContextVk(const gl::State &state, gl::ErrorSet *errorSet, RendererVk ...@@ -239,7 +239,6 @@ ContextVk::ContextVk(const gl::State &state, gl::ErrorSet *errorSet, RendererVk
mFlipYForCurrentSurface(false), mFlipYForCurrentSurface(false),
mIsAnyHostVisibleBufferWritten(false), mIsAnyHostVisibleBufferWritten(false),
mEmulateSeamfulCubeMapSampling(false), mEmulateSeamfulCubeMapSampling(false),
mEmulateSeamfulCubeMapSamplingWithSubgroupOps(false),
mUseOldRewriteStructSamplers(false), mUseOldRewriteStructSamplers(false),
mLastCompletedQueueSerial(renderer->nextSerial()), mLastCompletedQueueSerial(renderer->nextSerial()),
mCurrentQueueSerial(renderer->nextSerial()), mCurrentQueueSerial(renderer->nextSerial()),
...@@ -444,8 +443,7 @@ angle::Result ContextVk::initialize() ...@@ -444,8 +443,7 @@ angle::Result ContextVk::initialize()
ANGLE_TRY(synchronizeCpuGpuTime()); ANGLE_TRY(synchronizeCpuGpuTime());
} }
mEmulateSeamfulCubeMapSampling = mEmulateSeamfulCubeMapSampling = shouldEmulateSeamfulCubeMapSampling();
shouldEmulateSeamfulCubeMapSampling(&mEmulateSeamfulCubeMapSamplingWithSubgroupOps);
mUseOldRewriteStructSamplers = shouldUseOldRewriteStructSamplers(); mUseOldRewriteStructSamplers = shouldUseOldRewriteStructSamplers();
...@@ -2926,7 +2924,7 @@ vk::DescriptorSetLayoutDesc ContextVk::getDriverUniformsDescriptorSetDesc( ...@@ -2926,7 +2924,7 @@ vk::DescriptorSetLayoutDesc ContextVk::getDriverUniformsDescriptorSetDesc(
return desc; return desc;
} }
bool ContextVk::shouldEmulateSeamfulCubeMapSampling(bool *useSubgroupOpsOut) const bool ContextVk::shouldEmulateSeamfulCubeMapSampling() const
{ {
// Only allow seamful cube map sampling in non-webgl ES2. // Only allow seamful cube map sampling in non-webgl ES2.
if (mState.getClientMajorVersion() != 2 || mState.isWebGL()) if (mState.getClientMajorVersion() != 2 || mState.isWebGL())
...@@ -2939,15 +2937,6 @@ bool ContextVk::shouldEmulateSeamfulCubeMapSampling(bool *useSubgroupOpsOut) con ...@@ -2939,15 +2937,6 @@ bool ContextVk::shouldEmulateSeamfulCubeMapSampling(bool *useSubgroupOpsOut) con
return false; return false;
} }
// Use subgroup ops where available.
constexpr VkSubgroupFeatureFlags kSeamfulCubeMapSubgroupOperations =
VK_SUBGROUP_FEATURE_BASIC_BIT | VK_SUBGROUP_FEATURE_BALLOT_BIT |
VK_SUBGROUP_FEATURE_QUAD_BIT;
const VkSubgroupFeatureFlags deviceSupportedOperations =
mRenderer->getPhysicalDeviceSubgroupProperties().supportedOperations;
*useSubgroupOpsOut = (deviceSupportedOperations & kSeamfulCubeMapSubgroupOperations) ==
kSeamfulCubeMapSubgroupOperations;
return true; return true;
} }
......
...@@ -327,11 +327,7 @@ class ContextVk : public ContextImpl, public vk::Context, public vk::RenderPassO ...@@ -327,11 +327,7 @@ class ContextVk : public ContextImpl, public vk::Context, public vk::RenderPassO
void updateScissor(const gl::State &glState); void updateScissor(const gl::State &glState);
bool emulateSeamfulCubeMapSampling(bool *useSubgroupOpsOut) const bool emulateSeamfulCubeMapSampling() const { return mEmulateSeamfulCubeMapSampling; }
{
*useSubgroupOpsOut = mEmulateSeamfulCubeMapSamplingWithSubgroupOps;
return mEmulateSeamfulCubeMapSampling;
}
bool useOldRewriteStructSamplers() const { return mUseOldRewriteStructSamplers; } bool useOldRewriteStructSamplers() const { return mUseOldRewriteStructSamplers; }
...@@ -492,7 +488,7 @@ class ContextVk : public ContextImpl, public vk::Context, public vk::RenderPassO ...@@ -492,7 +488,7 @@ class ContextVk : public ContextImpl, public vk::Context, public vk::RenderPassO
void waitForSwapchainImageIfNecessary(); void waitForSwapchainImageIfNecessary();
bool shouldEmulateSeamfulCubeMapSampling(bool *useSubgroupOpsOut) const; bool shouldEmulateSeamfulCubeMapSampling() const;
bool shouldUseOldRewriteStructSamplers() const; bool shouldUseOldRewriteStructSamplers() const;
...@@ -557,10 +553,8 @@ class ContextVk : public ContextImpl, public vk::Context, public vk::RenderPassO ...@@ -557,10 +553,8 @@ class ContextVk : public ContextImpl, public vk::Context, public vk::RenderPassO
// at the end of the command buffer to make that write available to the host. // at the end of the command buffer to make that write available to the host.
bool mIsAnyHostVisibleBufferWritten; bool mIsAnyHostVisibleBufferWritten;
// Whether this context should do seamful cube map sampling emulation, and whether subgroup // Whether this context should do seamful cube map sampling emulation.
// operations should be used.
bool mEmulateSeamfulCubeMapSampling; bool mEmulateSeamfulCubeMapSampling;
bool mEmulateSeamfulCubeMapSamplingWithSubgroupOps;
// Whether this context should use the old version of the // Whether this context should use the old version of the
// RewriteStructSamplers pass. // RewriteStructSamplers pass.
......
...@@ -951,7 +951,6 @@ void GlslangWrapper::GetShaderSource(bool useOldRewriteStructSamplers, ...@@ -951,7 +951,6 @@ void GlslangWrapper::GetShaderSource(bool useOldRewriteStructSamplers,
angle::Result GlslangWrapper::GetShaderCode(vk::Context *context, angle::Result GlslangWrapper::GetShaderCode(vk::Context *context,
const gl::Caps &glCaps, const gl::Caps &glCaps,
bool enableLineRasterEmulation, bool enableLineRasterEmulation,
bool enableSubgroupOps,
const gl::ShaderMap<std::string> &shaderSources, const gl::ShaderMap<std::string> &shaderSources,
gl::ShaderMap<std::vector<uint32_t>> *shaderCodeOut) gl::ShaderMap<std::vector<uint32_t>> *shaderCodeOut)
{ {
...@@ -971,18 +970,17 @@ angle::Result GlslangWrapper::GetShaderCode(vk::Context *context, ...@@ -971,18 +970,17 @@ angle::Result GlslangWrapper::GetShaderCode(vk::Context *context,
kVersionDefine, kLineRasterDefine), kVersionDefine, kLineRasterDefine),
VK_ERROR_INVALID_SHADER_NV); VK_ERROR_INVALID_SHADER_NV);
return GetShaderCodeImpl(context, glCaps, enableSubgroupOps, patchedSources, shaderCodeOut); return GetShaderCodeImpl(context, glCaps, patchedSources, shaderCodeOut);
} }
else else
{ {
return GetShaderCodeImpl(context, glCaps, enableSubgroupOps, shaderSources, shaderCodeOut); return GetShaderCodeImpl(context, glCaps, shaderSources, shaderCodeOut);
} }
} }
// static // static
angle::Result GlslangWrapper::GetShaderCodeImpl(vk::Context *context, angle::Result GlslangWrapper::GetShaderCodeImpl(vk::Context *context,
const gl::Caps &glCaps, const gl::Caps &glCaps,
bool enableSubgroupOps,
const gl::ShaderMap<std::string> &shaderSources, const gl::ShaderMap<std::string> &shaderSources,
gl::ShaderMap<std::vector<uint32_t>> *shaderCodeOut) gl::ShaderMap<std::vector<uint32_t>> *shaderCodeOut)
{ {
...@@ -1018,11 +1016,6 @@ angle::Result GlslangWrapper::GetShaderCodeImpl(vk::Context *context, ...@@ -1018,11 +1016,6 @@ angle::Result GlslangWrapper::GetShaderCodeImpl(vk::Context *context,
glslang::TShader *shader = shaders[shaderType]; glslang::TShader *shader = shaders[shaderType];
shader->setStringsWithLengths(&shaderString, &shaderLength, 1); shader->setStringsWithLengths(&shaderString, &shaderLength, 1);
shader->setEntryPoint("main"); shader->setEntryPoint("main");
if (enableSubgroupOps)
{
// Enable SPIR-V 1.3 if to be able to use subgroup operations.
shader->setEnvTarget(glslang::EShTargetSpv, glslang::EShTargetSpv_1_3);
}
bool result = shader->parse(&builtInResources, 450, ECoreProfile, false, false, messages); bool result = shader->parse(&builtInResources, 450, ECoreProfile, false, false, messages);
if (!result) if (!result)
......
...@@ -30,14 +30,12 @@ class GlslangWrapper ...@@ -30,14 +30,12 @@ class GlslangWrapper
static angle::Result GetShaderCode(vk::Context *context, static angle::Result GetShaderCode(vk::Context *context,
const gl::Caps &glCaps, const gl::Caps &glCaps,
bool enableLineRasterEmulation, bool enableLineRasterEmulation,
bool enableSubgroupOps,
const gl::ShaderMap<std::string> &shaderSources, const gl::ShaderMap<std::string> &shaderSources,
gl::ShaderMap<std::vector<uint32_t>> *shaderCodesOut); gl::ShaderMap<std::vector<uint32_t>> *shaderCodesOut);
private: private:
static angle::Result GetShaderCodeImpl(vk::Context *context, static angle::Result GetShaderCodeImpl(vk::Context *context,
const gl::Caps &glCaps, const gl::Caps &glCaps,
bool enableSubgroupOps,
const gl::ShaderMap<std::string> &shaderSources, const gl::ShaderMap<std::string> &shaderSources,
gl::ShaderMap<std::vector<uint32_t>> *shaderCodesOut); gl::ShaderMap<std::vector<uint32_t>> *shaderCodesOut);
}; };
......
...@@ -304,16 +304,9 @@ angle::Result ProgramVk::ShaderInfo::initShaders(ContextVk *contextVk, ...@@ -304,16 +304,9 @@ angle::Result ProgramVk::ShaderInfo::initShaders(ContextVk *contextVk,
{ {
ASSERT(!valid()); ASSERT(!valid());
bool useSubgroupOpsWithSeamfulCubeMapEmulation = false;
bool emulateSeamfulCubeMapSampling =
contextVk->emulateSeamfulCubeMapSampling(&useSubgroupOpsWithSeamfulCubeMapEmulation);
bool useSubgroupOps =
emulateSeamfulCubeMapSampling && useSubgroupOpsWithSeamfulCubeMapEmulation;
gl::ShaderMap<std::vector<uint32_t>> shaderCodes; gl::ShaderMap<std::vector<uint32_t>> shaderCodes;
ANGLE_TRY(GlslangWrapper::GetShaderCode(contextVk, contextVk->getCaps(), ANGLE_TRY(GlslangWrapper::GetShaderCode(
enableLineRasterEmulation, useSubgroupOps, contextVk, contextVk->getCaps(), enableLineRasterEmulation, shaderSources, &shaderCodes));
shaderSources, &shaderCodes));
for (const gl::ShaderType shaderType : gl::AllShaderTypes()) for (const gl::ShaderType shaderType : gl::AllShaderTypes())
{ {
...@@ -1475,8 +1468,7 @@ angle::Result ProgramVk::updateTexturesDescriptorSet(ContextVk *contextVk) ...@@ -1475,8 +1468,7 @@ angle::Result ProgramVk::updateTexturesDescriptorSet(ContextVk *contextVk)
const gl::ActiveTextureArray<vk::TextureUnit> &activeTextures = contextVk->getActiveTextures(); const gl::ActiveTextureArray<vk::TextureUnit> &activeTextures = contextVk->getActiveTextures();
bool useSubgroupOps = false; bool emulateSeamfulCubeMapSampling = contextVk->emulateSeamfulCubeMapSampling();
bool emulateSeamfulCubeMapSampling = contextVk->emulateSeamfulCubeMapSampling(&useSubgroupOps);
bool useOldRewriteStructSamplers = contextVk->useOldRewriteStructSamplers(); bool useOldRewriteStructSamplers = contextVk->useOldRewriteStructSamplers();
std::unordered_map<std::string, uint32_t> mappedSamplerNameToBindingIndex; std::unordered_map<std::string, uint32_t> mappedSamplerNameToBindingIndex;
......
...@@ -40,17 +40,9 @@ std::shared_ptr<WaitableCompileEvent> ShaderVk::compile(const gl::Context *conte ...@@ -40,17 +40,9 @@ std::shared_ptr<WaitableCompileEvent> ShaderVk::compile(const gl::Context *conte
compileOptions |= SH_CLAMP_POINT_SIZE; compileOptions |= SH_CLAMP_POINT_SIZE;
} }
bool useSubgroupOps = false; if (contextVk->emulateSeamfulCubeMapSampling())
if (contextVk->emulateSeamfulCubeMapSampling(&useSubgroupOps))
{ {
if (useSubgroupOps) compileOptions |= SH_EMULATE_SEAMFUL_CUBE_MAP_SAMPLING;
{
compileOptions |= SH_EMULATE_SEAMFUL_CUBE_MAP_SAMPLING_WITH_SUBGROUP_OP;
}
else
{
compileOptions |= SH_EMULATE_SEAMFUL_CUBE_MAP_SAMPLING;
}
} }
if (contextVk->useOldRewriteStructSamplers()) if (contextVk->useOldRewriteStructSamplers())
......
...@@ -46,6 +46,8 @@ class CubeMapTextureTest : public ANGLETest ...@@ -46,6 +46,8 @@ class CubeMapTextureTest : public ANGLETest
void testTearDown() override { glDeleteProgram(mProgram); } void testTearDown() override { glDeleteProgram(mProgram); }
void runSampleCoordinateTransformTest(const char *shader);
GLuint mProgram; GLuint mProgram;
GLint mColorLocation; GLint mColorLocation;
}; };
...@@ -113,9 +115,7 @@ TEST_P(CubeMapTextureTest, RenderToFacesConsecutively) ...@@ -113,9 +115,7 @@ TEST_P(CubeMapTextureTest, RenderToFacesConsecutively)
EXPECT_GL_NO_ERROR(); EXPECT_GL_NO_ERROR();
} }
// Verify that cube map sampling follows the rules that map cubemap coordinates to coordinates void CubeMapTextureTest::runSampleCoordinateTransformTest(const char *shader)
// within each face. See section 3.7.5 of GLES2.0 (Cube Map Texture Selection).
TEST_P(CubeMapTextureTest, SampleCoordinateTransform)
{ {
// Fails to compile the shader. anglebug.com/3776 // Fails to compile the shader. anglebug.com/3776
ANGLE_SKIP_TEST_IF(IsOpenGL() && IsIntel() && IsWindows()); ANGLE_SKIP_TEST_IF(IsOpenGL() && IsIntel() && IsWindows());
...@@ -182,42 +182,7 @@ TEST_P(CubeMapTextureTest, SampleCoordinateTransform) ...@@ -182,42 +182,7 @@ TEST_P(CubeMapTextureTest, SampleCoordinateTransform)
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fboTex, 0); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fboTex, 0);
EXPECT_GL_NO_ERROR(); EXPECT_GL_NO_ERROR();
// Create a program that samples from 6x4 directions of the cubemap, draw and verify that the ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), shader);
// colors match the right color from |faceColors|.
constexpr char kFS[] = R"(precision mediump float;
uniform samplerCube texCube;
const mat4 coordInSection = mat4(
vec4(-0.5, -0.5, 0, 0),
vec4( 0.5, -0.5, 0, 0),
vec4(-0.5, 0.5, 0, 0),
vec4( 0.5, 0.5, 0, 0)
);
void main()
{
vec3 coord;
if (gl_FragCoord.x < 2.0)
{
coord.x = gl_FragCoord.x < 1.0 ? 1.0 : -1.0;
coord.zy = coordInSection[int(gl_FragCoord.y)].xy;
}
else if (gl_FragCoord.x < 4.0)
{
coord.y = gl_FragCoord.x < 3.0 ? 1.0 : -1.0;
coord.xz = coordInSection[int(gl_FragCoord.y)].xy;
}
else
{
coord.z = gl_FragCoord.x < 5.0 ? 1.0 : -1.0;
coord.xy = coordInSection[int(gl_FragCoord.y)].xy;
}
gl_FragColor = textureCube(texCube, coord);
})";
ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
glUseProgram(program); glUseProgram(program);
GLint texCubeLocation = glGetUniformLocation(program, "texCube"); GLint texCubeLocation = glGetUniformLocation(program, "texCube");
...@@ -261,6 +226,93 @@ void main() ...@@ -261,6 +226,93 @@ void main()
EXPECT_GL_NO_ERROR(); EXPECT_GL_NO_ERROR();
} }
// Verify that cube map sampling follows the rules that map cubemap coordinates to coordinates
// within each face. See section 3.7.5 of GLES2.0 (Cube Map Texture Selection).
TEST_P(CubeMapTextureTest, SampleCoordinateTransform)
{
// Create a program that samples from 6x4 directions of the cubemap, draw and verify that the
// colors match the right color from |faceColors|.
constexpr char kFS[] = R"(precision mediump float;
uniform samplerCube texCube;
const mat4 coordInSection = mat4(
vec4(-0.5, -0.5, 0, 0),
vec4( 0.5, -0.5, 0, 0),
vec4(-0.5, 0.5, 0, 0),
vec4( 0.5, 0.5, 0, 0)
);
void main()
{
vec3 coord;
if (gl_FragCoord.x < 2.0)
{
coord.x = gl_FragCoord.x < 1.0 ? 1.0 : -1.0;
coord.zy = coordInSection[int(gl_FragCoord.y)].xy;
}
else if (gl_FragCoord.x < 4.0)
{
coord.y = gl_FragCoord.x < 3.0 ? 1.0 : -1.0;
coord.xz = coordInSection[int(gl_FragCoord.y)].xy;
}
else
{
coord.z = gl_FragCoord.x < 5.0 ? 1.0 : -1.0;
coord.xy = coordInSection[int(gl_FragCoord.y)].xy;
}
gl_FragColor = textureCube(texCube, coord);
})";
runSampleCoordinateTransformTest(kFS);
}
// On Android Vulkan, unequal x and y derivatives cause this test to fail.
TEST_P(CubeMapTextureTest, SampleCoordinateTransformGrad)
{
ANGLE_SKIP_TEST_IF(IsAndroid() && IsVulkan()); // anglebug.com/3814
ANGLE_SKIP_TEST_IF(IsD3D11()); // anglebug.com/3856
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_texture_lod"));
constexpr char kFS[] = R"(#extension GL_EXT_shader_texture_lod : require
precision mediump float;
uniform samplerCube texCube;
const mat4 coordInSection = mat4(
vec4(-0.5, -0.5, 0, 0),
vec4( 0.5, -0.5, 0, 0),
vec4(-0.5, 0.5, 0, 0),
vec4( 0.5, 0.5, 0, 0)
);
void main()
{
vec3 coord;
if (gl_FragCoord.x < 2.0)
{
coord.x = gl_FragCoord.x < 1.0 ? 1.0 : -1.0;
coord.zy = coordInSection[int(gl_FragCoord.y)].xy;
}
else if (gl_FragCoord.x < 4.0)
{
coord.y = gl_FragCoord.x < 3.0 ? 1.0 : -1.0;
coord.xz = coordInSection[int(gl_FragCoord.y)].xy;
}
else
{
coord.z = gl_FragCoord.x < 5.0 ? 1.0 : -1.0;
coord.xy = coordInSection[int(gl_FragCoord.y)].xy;
}
gl_FragColor = textureCubeGradEXT(texCube, coord,
vec3(10.0, 10.0, 0.0), vec3(0.0, 10.0, 10.0));
})";
runSampleCoordinateTransformTest(kFS);
}
// Use this to select which configurations (e.g. which renderer, which GLES major version) these // Use this to select which configurations (e.g. which renderer, which GLES major version) these
// tests should be run against. // tests should be run against.
ANGLE_INSTANTIATE_TEST(CubeMapTextureTest, ANGLE_INSTANTIATE_TEST(CubeMapTextureTest,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment