diff --git a/next.json b/next.json index 1bd4ddaa6b..27eb7da52b 100644 --- a/next.json +++ b/next.json @@ -714,6 +714,14 @@ {"value": 1, "name":"linear"} ] }, + "address mode": { + "category": "enum", + "values": [ + {"value": 0, "name":"repeat"}, + {"value": 1, "name":"mirrored repeat"}, + {"value": 2, "name":"clamp to edge"} + ] + }, "float": { "category": "native" }, @@ -1018,6 +1026,14 @@ {"name": "min filter", "type": "filter mode"}, {"name": "mipmap filter", "type": "filter mode"} ] + }, + { + "name": "set address mode", + "args": [ + {"name": "address mode u", "type": "address mode"}, + {"name": "address mode v", "type": "address mode"}, + {"name": "address mode w", "type": "address mode"} + ] } ] }, diff --git a/src/backend/Sampler.cpp b/src/backend/Sampler.cpp index 4f95dc7199..697b73c995 100644 --- a/src/backend/Sampler.cpp +++ b/src/backend/Sampler.cpp @@ -27,6 +27,7 @@ namespace backend { enum SamplerSetProperties { SAMPLER_PROPERTY_FILTER = 0x1, + SAMPLER_PROPERTY_ADDRESS = 0x2, }; SamplerBuilder::SamplerBuilder(DeviceBase* device) : Builder(device) { } @@ -43,6 +44,18 @@ namespace backend { return mMipMapFilter; } + nxt::AddressMode SamplerBuilder::GetAddressModeU() const { + return mAddressModeU; + } + + nxt::AddressMode SamplerBuilder::GetAddressModeV() const { + return mAddressModeV; + } + + nxt::AddressMode SamplerBuilder::GetAddressModeW() const { + return mAddressModeW; + } + void SamplerBuilder::SetFilterMode(nxt::FilterMode magFilter, nxt::FilterMode minFilter, nxt::FilterMode mipMapFilter) { @@ -57,6 +70,20 @@ namespace backend { mPropertiesSet |= SAMPLER_PROPERTY_FILTER; } + void SamplerBuilder::SetAddressMode(nxt::AddressMode addressModeU, + nxt::AddressMode addressModeV, + nxt::AddressMode addressModeW) { + if ((mPropertiesSet & SAMPLER_PROPERTY_ADDRESS) != 0) { + HandleError("Sampler address property set multiple times"); + return; + } + + mAddressModeU = addressModeU; + mAddressModeV = addressModeV; + mAddressModeW = addressModeW; + mPropertiesSet |= SAMPLER_PROPERTY_ADDRESS; + } + SamplerBase* SamplerBuilder::GetResultImpl() { return mDevice->CreateSampler(this); } diff --git a/src/backend/Sampler.h b/src/backend/Sampler.h index bd1e1c7f60..31ff6f4af6 100644 --- a/src/backend/Sampler.h +++ b/src/backend/Sampler.h @@ -36,11 +36,19 @@ namespace backend { nxt::FilterMode GetMinFilter() const; nxt::FilterMode GetMipMapFilter() const; + nxt::AddressMode GetAddressModeU() const; + nxt::AddressMode GetAddressModeV() const; + nxt::AddressMode GetAddressModeW() const; + // NXT API void SetFilterMode(nxt::FilterMode magFilter, nxt::FilterMode minFilter, nxt::FilterMode mipMapFilter); + void SetAddressMode(nxt::AddressMode addressModeU, + nxt::AddressMode addressModeV, + nxt::AddressMode addressModeW); + private: friend class SamplerBase; @@ -51,6 +59,10 @@ namespace backend { nxt::FilterMode mMagFilter = nxt::FilterMode::Nearest; nxt::FilterMode mMinFilter = nxt::FilterMode::Nearest; nxt::FilterMode mMipMapFilter = nxt::FilterMode::Nearest; + + nxt::AddressMode mAddressModeU = nxt::AddressMode::ClampToEdge; + nxt::AddressMode mAddressModeV = nxt::AddressMode::ClampToEdge; + nxt::AddressMode mAddressModeW = nxt::AddressMode::ClampToEdge; }; } // namespace backend diff --git a/src/backend/d3d12/SamplerD3D12.cpp b/src/backend/d3d12/SamplerD3D12.cpp index 5ba83b5415..97b5156856 100644 --- a/src/backend/d3d12/SamplerD3D12.cpp +++ b/src/backend/d3d12/SamplerD3D12.cpp @@ -18,6 +18,21 @@ namespace backend { namespace d3d12 { + namespace { + D3D12_TEXTURE_ADDRESS_MODE AddressMode(nxt::AddressMode mode) { + switch (mode) { + case nxt::AddressMode::Repeat: + return D3D12_TEXTURE_ADDRESS_MODE_WRAP; + case nxt::AddressMode::MirroredRepeat: + return D3D12_TEXTURE_ADDRESS_MODE_MIRROR; + case nxt::AddressMode::ClampToEdge: + return D3D12_TEXTURE_ADDRESS_MODE_CLAMP; + default: + UNREACHABLE(); + } + } + } // namespace + Sampler::Sampler(SamplerBuilder* builder) : SamplerBase(builder) { // https://msdn.microsoft.com/en-us/library/windows/desktop/dn770367(v=vs.85).aspx // hex value, decimal value, min linear, mag linear, mip linear @@ -61,9 +76,9 @@ namespace backend { namespace d3d12 { } mSamplerDesc.Filter = static_cast(mode); - mSamplerDesc.AddressU = D3D12_TEXTURE_ADDRESS_MODE_WRAP; - mSamplerDesc.AddressV = D3D12_TEXTURE_ADDRESS_MODE_WRAP; - mSamplerDesc.AddressW = D3D12_TEXTURE_ADDRESS_MODE_WRAP; + mSamplerDesc.AddressU = AddressMode(builder->GetAddressModeU()); + mSamplerDesc.AddressV = AddressMode(builder->GetAddressModeV()); + mSamplerDesc.AddressW = AddressMode(builder->GetAddressModeW()); mSamplerDesc.MipLODBias = 0.f; mSamplerDesc.MaxAnisotropy = 1; mSamplerDesc.ComparisonFunc = D3D12_COMPARISON_FUNC_ALWAYS; diff --git a/src/backend/metal/SamplerMTL.mm b/src/backend/metal/SamplerMTL.mm index 6d66b12318..3b70c4edd4 100644 --- a/src/backend/metal/SamplerMTL.mm +++ b/src/backend/metal/SamplerMTL.mm @@ -36,6 +36,17 @@ namespace backend { namespace metal { return MTLSamplerMipFilterLinear; } } + + MTLSamplerAddressMode AddressMode(nxt::AddressMode mode) { + switch (mode) { + case nxt::AddressMode::Repeat: + return MTLSamplerAddressModeRepeat; + case nxt::AddressMode::MirroredRepeat: + return MTLSamplerAddressModeMirrorRepeat; + case nxt::AddressMode::ClampToEdge: + return MTLSamplerAddressModeClampToEdge; + } + } } Sampler::Sampler(SamplerBuilder* builder) : SamplerBase(builder) { @@ -45,7 +56,10 @@ namespace backend { namespace metal { desc.magFilter = FilterModeToMinMagFilter(builder->GetMagFilter()); desc.mipFilter = FilterModeToMipFilter(builder->GetMipMapFilter()); - // TODO(kainino@chromium.org): wrap modes + desc.sAddressMode = AddressMode(builder->GetAddressModeU()); + desc.tAddressMode = AddressMode(builder->GetAddressModeV()); + desc.rAddressMode = AddressMode(builder->GetAddressModeW()); + auto mtlDevice = ToBackend(builder->GetDevice())->GetMTLDevice(); mMtlSamplerState = [mtlDevice newSamplerStateWithDescriptor:desc]; } diff --git a/src/backend/opengl/SamplerGL.cpp b/src/backend/opengl/SamplerGL.cpp index 2da9b9d627..a668fd8dfe 100644 --- a/src/backend/opengl/SamplerGL.cpp +++ b/src/backend/opengl/SamplerGL.cpp @@ -54,6 +54,20 @@ namespace backend { namespace opengl { UNREACHABLE(); } } + + GLenum WrapMode(nxt::AddressMode mode) { + switch (mode) { + case nxt::AddressMode::Repeat: + return GL_REPEAT; + case nxt::AddressMode::MirroredRepeat: + return GL_MIRRORED_REPEAT; + case nxt::AddressMode::ClampToEdge: + return GL_CLAMP_TO_EDGE; + default: + UNREACHABLE(); + } + } + } // namespace Sampler::Sampler(SamplerBuilder* builder) : SamplerBase(builder) { @@ -61,6 +75,9 @@ namespace backend { namespace opengl { glSamplerParameteri(mHandle, GL_TEXTURE_MAG_FILTER, MagFilterMode(builder->GetMagFilter())); glSamplerParameteri(mHandle, GL_TEXTURE_MIN_FILTER, MinFilterMode(builder->GetMinFilter(), builder->GetMipMapFilter())); + glSamplerParameteri(mHandle, GL_TEXTURE_WRAP_R, WrapMode(builder->GetAddressModeW())); + glSamplerParameteri(mHandle, GL_TEXTURE_WRAP_S, WrapMode(builder->GetAddressModeU())); + glSamplerParameteri(mHandle, GL_TEXTURE_WRAP_T, WrapMode(builder->GetAddressModeV())); } GLuint Sampler::GetHandle() const {