diff --git a/src/dawn_native/opengl/CommandBufferGL.cpp b/src/dawn_native/opengl/CommandBufferGL.cpp index 9fafb6f4fb..2dccfe5b0e 100644 --- a/src/dawn_native/opengl/CommandBufferGL.cpp +++ b/src/dawn_native/opengl/CommandBufferGL.cpp @@ -246,12 +246,18 @@ namespace dawn_native { namespace opengl { } break; case dawn::BindingType::Sampler: { - GLuint sampler = - ToBackend(group->GetBindingAsSampler(bindingIndex))->GetHandle(); + Sampler* sampler = ToBackend(group->GetBindingAsSampler(bindingIndex)); GLuint samplerIndex = indices[bindingIndex]; - for (auto unit : pipeline->GetTextureUnitsForSampler(samplerIndex)) { - gl.BindSampler(unit, sampler); + for (PipelineGL::SamplerUnit unit : + pipeline->GetTextureUnitsForSampler(samplerIndex)) { + // Only use filtering for certain texture units, because int and uint + // texture are only complete without filtering + if (unit.shouldUseFiltering) { + gl.BindSampler(unit.unit, sampler->GetFilteringHandle()); + } else { + gl.BindSampler(unit.unit, sampler->GetNonFilteringHandle()); + } } } break; diff --git a/src/dawn_native/opengl/PipelineGL.cpp b/src/dawn_native/opengl/PipelineGL.cpp index e04dbc7bab..f7adf952f3 100644 --- a/src/dawn_native/opengl/PipelineGL.cpp +++ b/src/dawn_native/opengl/PipelineGL.cpp @@ -173,20 +173,27 @@ namespace dawn_native { namespace opengl { gl.Uniform1i(location, textureUnit); - GLuint samplerIndex = - indices[combined.samplerLocation.group][combined.samplerLocation.binding]; - mUnitsForSamplers[samplerIndex].push_back(textureUnit); - GLuint textureIndex = indices[combined.textureLocation.group][combined.textureLocation.binding]; mUnitsForTextures[textureIndex].push_back(textureUnit); + dawn::TextureComponentType componentType = + layout->GetBindGroupLayout(combined.textureLocation.group) + ->GetBindingInfo() + .textureComponentTypes[combined.textureLocation.binding]; + bool shouldUseFiltering = componentType == dawn::TextureComponentType::Float; + + GLuint samplerIndex = + indices[combined.samplerLocation.group][combined.samplerLocation.binding]; + mUnitsForSamplers[samplerIndex].push_back({textureUnit, shouldUseFiltering}); + textureUnit++; } } } - const std::vector& PipelineGL::GetTextureUnitsForSampler(GLuint index) const { + const std::vector& PipelineGL::GetTextureUnitsForSampler( + GLuint index) const { ASSERT(index < mUnitsForSamplers.size()); return mUnitsForSamplers[index]; } diff --git a/src/dawn_native/opengl/PipelineGL.h b/src/dawn_native/opengl/PipelineGL.h index b5745892c3..6a081c119e 100644 --- a/src/dawn_native/opengl/PipelineGL.h +++ b/src/dawn_native/opengl/PipelineGL.h @@ -39,7 +39,13 @@ namespace dawn_native { namespace opengl { using BindingLocations = std::array, kMaxBindGroups>; - const std::vector& GetTextureUnitsForSampler(GLuint index) const; + // For each unit a sampler is bound to we need to know if we should use filtering or not + // because int and uint texture are only complete without filtering. + struct SamplerUnit { + GLuint unit; + bool shouldUseFiltering; + }; + const std::vector& GetTextureUnitsForSampler(GLuint index) const; const std::vector& GetTextureUnitsForTextureView(GLuint index) const; GLuint GetProgramHandle() const; @@ -47,7 +53,7 @@ namespace dawn_native { namespace opengl { private: GLuint mProgram; - std::vector> mUnitsForSamplers; + std::vector> mUnitsForSamplers; std::vector> mUnitsForTextures; }; diff --git a/src/dawn_native/opengl/SamplerGL.cpp b/src/dawn_native/opengl/SamplerGL.cpp index 832a4ffc27..17bf353ed5 100644 --- a/src/dawn_native/opengl/SamplerGL.cpp +++ b/src/dawn_native/opengl/SamplerGL.cpp @@ -76,26 +76,53 @@ namespace dawn_native { namespace opengl { : SamplerBase(device, descriptor) { const OpenGLFunctions& gl = ToBackend(GetDevice())->gl; - gl.GenSamplers(1, &mHandle); - gl.SamplerParameteri(mHandle, GL_TEXTURE_MAG_FILTER, MagFilterMode(descriptor->magFilter)); - gl.SamplerParameteri(mHandle, GL_TEXTURE_MIN_FILTER, - MinFilterMode(descriptor->minFilter, descriptor->mipmapFilter)); - gl.SamplerParameteri(mHandle, GL_TEXTURE_WRAP_R, WrapMode(descriptor->addressModeW)); - gl.SamplerParameteri(mHandle, GL_TEXTURE_WRAP_S, WrapMode(descriptor->addressModeU)); - gl.SamplerParameteri(mHandle, GL_TEXTURE_WRAP_T, WrapMode(descriptor->addressModeV)); + gl.GenSamplers(1, &mFilteringHandle); + SetupGLSampler(mFilteringHandle, descriptor, false); - gl.SamplerParameterf(mHandle, GL_TEXTURE_MIN_LOD, descriptor->lodMinClamp); - gl.SamplerParameterf(mHandle, GL_TEXTURE_MAX_LOD, descriptor->lodMaxClamp); + gl.GenSamplers(1, &mNonFilteringHandle); + SetupGLSampler(mNonFilteringHandle, descriptor, true); + } + + Sampler::~Sampler() { + const OpenGLFunctions& gl = ToBackend(GetDevice())->gl; + gl.DeleteSamplers(1, &mFilteringHandle); + gl.DeleteSamplers(1, &mNonFilteringHandle); + } + + void Sampler::SetupGLSampler(GLuint sampler, + const SamplerDescriptor* descriptor, + bool forceNearest) { + const OpenGLFunctions& gl = ToBackend(GetDevice())->gl; + + if (forceNearest) { + gl.SamplerParameteri(sampler, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + gl.SamplerParameteri(sampler, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST); + } else { + gl.SamplerParameteri(sampler, GL_TEXTURE_MAG_FILTER, + MagFilterMode(descriptor->magFilter)); + gl.SamplerParameteri(sampler, GL_TEXTURE_MIN_FILTER, + MinFilterMode(descriptor->minFilter, descriptor->mipmapFilter)); + } + gl.SamplerParameteri(sampler, GL_TEXTURE_WRAP_R, WrapMode(descriptor->addressModeW)); + gl.SamplerParameteri(sampler, GL_TEXTURE_WRAP_S, WrapMode(descriptor->addressModeU)); + gl.SamplerParameteri(sampler, GL_TEXTURE_WRAP_T, WrapMode(descriptor->addressModeV)); + + gl.SamplerParameterf(sampler, GL_TEXTURE_MIN_LOD, descriptor->lodMinClamp); + gl.SamplerParameterf(sampler, GL_TEXTURE_MAX_LOD, descriptor->lodMaxClamp); if (ToOpenGLCompareFunction(descriptor->compare) != GL_NEVER) { - gl.SamplerParameteri(mHandle, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE); - gl.SamplerParameteri(mHandle, GL_TEXTURE_COMPARE_FUNC, + gl.SamplerParameteri(sampler, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE); + gl.SamplerParameteri(sampler, GL_TEXTURE_COMPARE_FUNC, ToOpenGLCompareFunction(descriptor->compare)); } } - GLuint Sampler::GetHandle() const { - return mHandle; + GLuint Sampler::GetFilteringHandle() const { + return mFilteringHandle; + } + + GLuint Sampler::GetNonFilteringHandle() const { + return mNonFilteringHandle; } }} // namespace dawn_native::opengl diff --git a/src/dawn_native/opengl/SamplerGL.h b/src/dawn_native/opengl/SamplerGL.h index 3c4911be4e..19b185b10f 100644 --- a/src/dawn_native/opengl/SamplerGL.h +++ b/src/dawn_native/opengl/SamplerGL.h @@ -26,11 +26,19 @@ namespace dawn_native { namespace opengl { class Sampler : public SamplerBase { public: Sampler(Device* device, const SamplerDescriptor* descriptor); + ~Sampler(); - GLuint GetHandle() const; + GLuint GetFilteringHandle() const; + GLuint GetNonFilteringHandle() const; private: - GLuint mHandle; + void SetupGLSampler(GLuint sampler, const SamplerDescriptor* descriptor, bool forceNearest); + + GLuint mFilteringHandle; + + // This is a sampler equivalent to mFilteringHandle except that it uses NEAREST filtering + // for everything, which is important to preserve texture completeness for u/int textures. + GLuint mNonFilteringHandle; }; }} // namespace dawn_native::opengl diff --git a/src/tests/end2end/TextureFormatTests.cpp b/src/tests/end2end/TextureFormatTests.cpp index b530c6969a..79029cfcce 100644 --- a/src/tests/end2end/TextureFormatTests.cpp +++ b/src/tests/end2end/TextureFormatTests.cpp @@ -498,146 +498,92 @@ TEST_P(TextureFormatTest, RGBA8Snorm) { // Test the R8Uint format TEST_P(TextureFormatTest, R8Uint) { - // TODO(cwallez@chromium.org): This fails on the Intel GL driver, understand why. - DAWN_SKIP_TEST_IF(IsOpenGL() && IsIntel()); - DoUintTest({dawn::TextureFormat::R8Uint, 1, dawn::TextureComponentType::Uint, 1}); } // Test the RG8Uint format TEST_P(TextureFormatTest, RG8Uint) { - // TODO(cwallez@chromium.org): This fails on the Intel GL driver, understand why. - DAWN_SKIP_TEST_IF(IsOpenGL() && IsIntel()); - DoUintTest({dawn::TextureFormat::RG8Uint, 2, dawn::TextureComponentType::Uint, 2}); } // Test the RGBA8Uint format TEST_P(TextureFormatTest, RGBA8Uint) { - // TODO(cwallez@chromium.org): This fails on the Intel GL driver, understand why. - DAWN_SKIP_TEST_IF(IsOpenGL() && IsIntel()); - DoUintTest({dawn::TextureFormat::RGBA8Uint, 4, dawn::TextureComponentType::Uint, 4}); } // Test the R16Uint format TEST_P(TextureFormatTest, R16Uint) { - // TODO(cwallez@chromium.org): This fails on the Intel GL driver, understand why. - DAWN_SKIP_TEST_IF(IsOpenGL() && IsIntel()); - DoUintTest({dawn::TextureFormat::R16Uint, 2, dawn::TextureComponentType::Uint, 1}); } // Test the RG16Uint format TEST_P(TextureFormatTest, RG16Uint) { - // TODO(cwallez@chromium.org): This fails on the Intel GL driver, understand why. - DAWN_SKIP_TEST_IF(IsOpenGL() && IsIntel()); - DoUintTest({dawn::TextureFormat::RG16Uint, 4, dawn::TextureComponentType::Uint, 2}); } // Test the RGBA16Uint format TEST_P(TextureFormatTest, RGBA16Uint) { - // TODO(cwallez@chromium.org): This fails on the Intel GL driver, understand why. - DAWN_SKIP_TEST_IF(IsOpenGL() && IsIntel()); - DoUintTest({dawn::TextureFormat::RGBA16Uint, 8, dawn::TextureComponentType::Uint, 4}); } // Test the R32Uint format TEST_P(TextureFormatTest, R32Uint) { - // TODO(cwallez@chromium.org): This fails on the Intel GL driver, understand why. - DAWN_SKIP_TEST_IF(IsOpenGL() && IsIntel()); - DoUintTest({dawn::TextureFormat::R32Uint, 4, dawn::TextureComponentType::Uint, 1}); } // Test the RG32Uint format TEST_P(TextureFormatTest, RG32Uint) { - // TODO(cwallez@chromium.org): This fails on the Intel GL driver, understand why. - DAWN_SKIP_TEST_IF(IsOpenGL() && IsIntel()); - DoUintTest({dawn::TextureFormat::RG32Uint, 8, dawn::TextureComponentType::Uint, 2}); } // Test the RGBA32Uint format TEST_P(TextureFormatTest, RGBA32Uint) { - // TODO(cwallez@chromium.org): This fails on the Intel GL driver, understand why. - DAWN_SKIP_TEST_IF(IsOpenGL() && IsIntel()); - DoUintTest( {dawn::TextureFormat::RGBA32Uint, 16, dawn::TextureComponentType::Uint, 4}); } // Test the R8Sint format TEST_P(TextureFormatTest, R8Sint) { - // TODO(cwallez@chromium.org): This fails on the Intel GL driver, understand why. - DAWN_SKIP_TEST_IF(IsOpenGL() && IsIntel()); - DoSintTest({dawn::TextureFormat::R8Sint, 1, dawn::TextureComponentType::Sint, 1}); } // Test the RG8Sint format TEST_P(TextureFormatTest, RG8Sint) { - // TODO(cwallez@chromium.org): This fails on the Intel GL driver, understand why. - DAWN_SKIP_TEST_IF(IsOpenGL() && IsIntel()); - DoSintTest({dawn::TextureFormat::RG8Sint, 2, dawn::TextureComponentType::Sint, 2}); } // Test the RGBA8Sint format TEST_P(TextureFormatTest, RGBA8Sint) { - // TODO(cwallez@chromium.org): This fails on the Intel GL driver, understand why. - DAWN_SKIP_TEST_IF(IsOpenGL() && IsIntel()); - DoSintTest({dawn::TextureFormat::RGBA8Sint, 4, dawn::TextureComponentType::Sint, 4}); } // Test the R16Sint format TEST_P(TextureFormatTest, R16Sint) { - // TODO(cwallez@chromium.org): This fails on the Intel GL driver, understand why. - DAWN_SKIP_TEST_IF(IsOpenGL() && IsIntel()); - DoSintTest({dawn::TextureFormat::R16Sint, 2, dawn::TextureComponentType::Sint, 1}); } // Test the RG16Sint format TEST_P(TextureFormatTest, RG16Sint) { - // TODO(cwallez@chromium.org): This fails on the Intel GL driver, understand why. - DAWN_SKIP_TEST_IF(IsOpenGL() && IsIntel()); - DoSintTest({dawn::TextureFormat::RG16Sint, 4, dawn::TextureComponentType::Sint, 2}); } // Test the RGBA16Sint format TEST_P(TextureFormatTest, RGBA16Sint) { - // TODO(cwallez@chromium.org): This fails on the Intel GL driver, understand why. - DAWN_SKIP_TEST_IF(IsOpenGL() && IsIntel()); - DoSintTest({dawn::TextureFormat::RGBA16Sint, 8, dawn::TextureComponentType::Sint, 4}); } // Test the R32Sint format TEST_P(TextureFormatTest, R32Sint) { - // TODO(cwallez@chromium.org): This fails on the Intel GL driver, understand why. - DAWN_SKIP_TEST_IF(IsOpenGL() && IsIntel()); - DoSintTest({dawn::TextureFormat::R32Sint, 4, dawn::TextureComponentType::Sint, 1}); } // Test the RG32Sint format TEST_P(TextureFormatTest, RG32Sint) { - // TODO(cwallez@chromium.org): This fails on the Intel GL driver, understand why. - DAWN_SKIP_TEST_IF(IsOpenGL() && IsIntel()); - DoSintTest({dawn::TextureFormat::RG32Sint, 8, dawn::TextureComponentType::Sint, 2}); } // Test the RGBA32Sint format TEST_P(TextureFormatTest, RGBA32Sint) { - // TODO(cwallez@chromium.org): This fails on the Intel GL driver, understand why. - DAWN_SKIP_TEST_IF(IsOpenGL() && IsIntel()); - DoSintTest({dawn::TextureFormat::RGBA32Sint, 16, dawn::TextureComponentType::Sint, 4}); }