diff --git a/include/boo/graphicsdev/IGraphicsDataFactory.hpp b/include/boo/graphicsdev/IGraphicsDataFactory.hpp index eb18649..40ab3bb 100644 --- a/include/boo/graphicsdev/IGraphicsDataFactory.hpp +++ b/include/boo/graphicsdev/IGraphicsDataFactory.hpp @@ -69,13 +69,18 @@ enum class TextureFormat enum class TextureClampMode { Repeat, - ClampToWhite + ClampToWhite, + ClampToEdge }; /** Typeless texture */ struct ITexture : IObj { TextureType type() const { return m_type; } + + /* Only applies on GL and Vulkan. Use shader semantics on other platforms */ + virtual void setClampMode(TextureClampMode mode) {} + protected: TextureType m_type; explicit ITexture(TextureType type) : m_type(type) {} diff --git a/include/boo/graphicsdev/Vulkan.hpp b/include/boo/graphicsdev/Vulkan.hpp index 3226d95..1452890 100644 --- a/include/boo/graphicsdev/Vulkan.hpp +++ b/include/boo/graphicsdev/Vulkan.hpp @@ -44,7 +44,7 @@ struct VulkanContext VkRenderPass m_pass; VkCommandPool m_loadPool; VkCommandBuffer m_loadCmdBuf; - VkSampler m_linearSamplers[2]; + VkSampler m_linearSamplers[3]; VkFormat m_displayFormat; struct Window diff --git a/lib/graphicsdev/D3D11.cpp b/lib/graphicsdev/D3D11.cpp index 36b0afd..773b605 100644 --- a/lib/graphicsdev/D3D11.cpp +++ b/lib/graphicsdev/D3D11.cpp @@ -1017,8 +1017,8 @@ struct D3D11CommandQueue : IGraphicsCommandQueue cbind->bind(m_deferredCtx.Get(), m_fillBuf); m_cmdLists[m_fillBuf].resTokens.push_back(binding.get()); - ID3D11SamplerState* samp[] = {m_ctx->m_ss[0].Get(), m_ctx->m_ss[1].Get()}; - m_deferredCtx->PSSetSamplers(0, 2, samp); + ID3D11SamplerState* samp[] = {m_ctx->m_ss[0].Get(), m_ctx->m_ss[1].Get(), m_ctx->m_ss[2].Get()}; + m_deferredCtx->PSSetSamplers(0, 3, samp); } boo::ObjToken m_boundTarget; diff --git a/lib/graphicsdev/D3D12.cpp b/lib/graphicsdev/D3D12.cpp index 6192b83..44b939b 100644 --- a/lib/graphicsdev/D3D12.cpp +++ b/lib/graphicsdev/D3D12.cpp @@ -1681,11 +1681,13 @@ public: { CD3DX12_STATIC_SAMPLER_DESC(0), CD3DX12_STATIC_SAMPLER_DESC(1, D3D12_FILTER_ANISOTROPIC, D3D12_TEXTURE_ADDRESS_MODE_BORDER, - D3D12_TEXTURE_ADDRESS_MODE_BORDER, D3D12_TEXTURE_ADDRESS_MODE_BORDER) + D3D12_TEXTURE_ADDRESS_MODE_BORDER, D3D12_TEXTURE_ADDRESS_MODE_BORDER), + CD3DX12_STATIC_SAMPLER_DESC(2, D3D12_FILTER_ANISOTROPIC, D3D12_TEXTURE_ADDRESS_MODE_CLAMP, + D3D12_TEXTURE_ADDRESS_MODE_CLAMP, D3D12_TEXTURE_ADDRESS_MODE_CLAMP) }; ThrowIfFailed(D3D12SerializeRootSignaturePROC( - &CD3DX12_ROOT_SIGNATURE_DESC(1, rootParms, 2, samplers, + &CD3DX12_ROOT_SIGNATURE_DESC(1, rootParms, 3, samplers, D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT), D3D_ROOT_SIGNATURE_VERSION_1, &rsOutBlob, &rsErrorBlob)); diff --git a/lib/graphicsdev/GL.cpp b/lib/graphicsdev/GL.cpp index b81093d..7901582 100644 --- a/lib/graphicsdev/GL.cpp +++ b/lib/graphicsdev/GL.cpp @@ -172,6 +172,13 @@ static void SetClampMode(GLenum target, TextureClampMode clampMode) glTexParameterfv(target, GL_TEXTURE_BORDER_COLOR, color); break; } + case TextureClampMode::ClampToEdge: + { + glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(target, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); + break; + } } } @@ -249,6 +256,12 @@ class GLTextureS : public GraphicsDataNode public: ~GLTextureS() { glDeleteTextures(1, &m_tex); } + void setClampMode(TextureClampMode mode) + { + glBindTexture(GL_TEXTURE_2D, m_tex); + SetClampMode(GL_TEXTURE_2D, mode); + } + void bind(size_t idx) const { glActiveTexture(GL_TEXTURE0 + idx); @@ -306,6 +319,12 @@ class GLTextureSA : public GraphicsDataNode public: ~GLTextureSA() { glDeleteTextures(1, &m_tex); } + void setClampMode(TextureClampMode mode) + { + glBindTexture(GL_TEXTURE_2D_ARRAY, m_tex); + SetClampMode(GL_TEXTURE_2D_ARRAY, mode); + } + void bind(size_t idx) const { glActiveTexture(GL_TEXTURE0 + idx); @@ -389,6 +408,15 @@ public: m_validMask = 0; } + void setClampMode(TextureClampMode mode) + { + for (int i=0 ; i<3 ; ++i) + { + glBindTexture(GL_TEXTURE_2D, m_texs[i]); + SetClampMode(GL_TEXTURE_2D, mode); + } + } + void bind(size_t idx, int b) { glActiveTexture(GL_TEXTURE0 + idx); @@ -409,6 +437,8 @@ class GLTextureR : public GraphicsDataNode size_t m_width = 0; size_t m_height = 0; size_t m_samples = 0; + size_t m_colorBindCount; + size_t m_depthBindCount; GLenum m_target; GLTextureR(const ObjToken& parent, GLCommandQueue* q, size_t width, size_t height, size_t samples, TextureClampMode clampMode, size_t colorBindCount, size_t depthBindCount); @@ -420,6 +450,20 @@ public: glDeleteFramebuffers(1, &m_fbo); } + void setClampMode(TextureClampMode mode) + { + for (int i=0 ; i& parent, GLCommandQueue* q, size_t width, size_t height, size_t samples, TextureClampMode clampMode, size_t colorBindingCount, size_t depthBindingCount) -: GraphicsDataNode(parent), m_q(q), m_width(width), m_height(height), m_samples(samples) +: GraphicsDataNode(parent), m_q(q), m_width(width), m_height(height), m_samples(samples), + m_colorBindCount(colorBindingCount), m_depthBindCount(depthBindingCount) { glGenTextures(2, m_texs); if (colorBindingCount) diff --git a/lib/graphicsdev/Vulkan.cpp b/lib/graphicsdev/Vulkan.cpp index 29455cf..144a6e3 100644 --- a/lib/graphicsdev/Vulkan.cpp +++ b/lib/graphicsdev/Vulkan.cpp @@ -608,6 +608,12 @@ void VulkanContext::initSwapChain(VulkanContext::Window& windowCtx, VkSurfaceKHR samplerInfo.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE; ThrowIfFailed(vk::CreateSampler(m_dev, &samplerInfo, nullptr, &m_linearSamplers[1])); + /* Create shared edge-clamped sampler */ + samplerInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; + samplerInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; + samplerInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; + ThrowIfFailed(vk::CreateSampler(m_dev, &samplerInfo, nullptr, &m_linearSamplers[2])); + /* images */ sc.m_bufs.resize(swapchainImageCount); for (uint32_t i=0 ; im_dev, m_cpuMem, nullptr); } + void setClampMode(TextureClampMode mode) + { + m_descInfo.sampler = m_ctx->m_linearSamplers[int(mode)]; + } + void deleteUploadObjects() { vk::DestroyBuffer(m_ctx->m_dev, m_cpuBuf, nullptr); @@ -1230,6 +1241,11 @@ public: vk::FreeMemory(m_ctx->m_dev, m_cpuMem, nullptr); } + void setClampMode(TextureClampMode mode) + { + m_descInfo.sampler = m_ctx->m_linearSamplers[int(mode)]; + } + void deleteUploadObjects() { vk::DestroyBuffer(m_ctx->m_dev, m_cpuBuf, nullptr); @@ -1438,6 +1454,12 @@ public: VkDescriptorImageInfo m_descInfo[2]; ~VulkanTextureD(); + void setClampMode(TextureClampMode mode) + { + for (int i=0 ; i<2 ; ++i) + m_descInfo[i].sampler = m_ctx->m_linearSamplers[int(mode)]; + } + void load(const void* data, size_t sz); void* map(size_t sz); void unmap(); @@ -1723,6 +1745,14 @@ public: VkImageLayout m_colorBindLayout[MAX_BIND_TEXS] = {}; VkImageLayout m_depthBindLayout[MAX_BIND_TEXS] = {}; + void setClampMode(TextureClampMode mode) + { + for (size_t i=0 ; im_linearSamplers[int(mode)]; + for (size_t i=0 ; im_linearSamplers[int(mode)]; + } + void doDestroy(); ~VulkanTextureR(); diff --git a/lib/mac/ApplicationCocoa.mm b/lib/mac/ApplicationCocoa.mm index 3d905c6..b34f81e 100644 --- a/lib/mac/ApplicationCocoa.mm +++ b/lib/mac/ApplicationCocoa.mm @@ -136,12 +136,12 @@ public: dispatch_sync(dispatch_get_main_queue(), ^{ /* Ends modal run loop and continues Cocoa termination */ - [[NSApplication sharedApplication] replyToApplicationShouldTerminate:YES]; + [NSApp replyToApplicationShouldTerminate:YES]; /* If this is reached, application didn't spawn any windows * and must be explicitly terminated */ m_terminateNow = true; - [[NSApplication sharedApplication] terminate:nil]; + [NSApp terminate:nil]; }); #else /* Return control to main() */ @@ -218,7 +218,7 @@ int ApplicationRun(IApplication::EPlatformType platform, /* Never deallocated to ensure window destructors have access */ APP = new ApplicationCocoa(cb, uniqueName, friendlyName, pname, args); } - [[NSApplication sharedApplication] run]; + [NSApp run]; ApplicationCocoa* appCocoa = static_cast(APP); if (appCocoa->m_clientThread.joinable()) appCocoa->m_clientThread.join(); diff --git a/lib/mac/WindowCocoa.mm b/lib/mac/WindowCocoa.mm index e1d5808..417eedb 100644 --- a/lib/mac/WindowCocoa.mm +++ b/lib/mac/WindowCocoa.mm @@ -139,6 +139,7 @@ public: } } + std::mutex m_callbackMutex; IWindowCallback* m_callback = nullptr; void waitForRetrace(IAudioVoiceEngine* voxEngine) { @@ -222,6 +223,7 @@ public: void _setCallback(IWindowCallback* cb) { + std::lock_guard lk(m_callbackMutex); m_callback = cb; } @@ -380,6 +382,7 @@ public: void _setCallback(IWindowCallback* cb) { + std::lock_guard lk(m_callbackMutex); m_callback = cb; } @@ -481,6 +484,7 @@ IGraphicsContext* _GraphicsContextCocoaMetalNew(IGraphicsContext::EGraphicsAPI a - (BOOL)hasMarkedText { + std::lock_guard lk(booContext->m_callbackMutex); if (booContext->m_callback) { boo::ITextInputCallback* textCb = booContext->m_callback->getTextInputCallback(); @@ -492,6 +496,7 @@ IGraphicsContext* _GraphicsContextCocoaMetalNew(IGraphicsContext::EGraphicsAPI a - (NSRange)markedRange { + std::lock_guard lk(booContext->m_callbackMutex); if (booContext->m_callback) { boo::ITextInputCallback* textCb = booContext->m_callback->getTextInputCallback(); @@ -506,6 +511,7 @@ IGraphicsContext* _GraphicsContextCocoaMetalNew(IGraphicsContext::EGraphicsAPI a - (NSRange)selectedRange { + std::lock_guard lk(booContext->m_callbackMutex); if (booContext->m_callback) { boo::ITextInputCallback* textCb = booContext->m_callback->getTextInputCallback(); @@ -520,6 +526,7 @@ IGraphicsContext* _GraphicsContextCocoaMetalNew(IGraphicsContext::EGraphicsAPI a - (void)setMarkedText:(id)aString selectedRange:(NSRange)selectedRange replacementRange:(NSRange)replacementRange { + std::lock_guard lk(booContext->m_callbackMutex); if (booContext->m_callback) { boo::ITextInputCallback* textCb = booContext->m_callback->getTextInputCallback(); @@ -538,6 +545,7 @@ IGraphicsContext* _GraphicsContextCocoaMetalNew(IGraphicsContext::EGraphicsAPI a - (void)unmarkText { + std::lock_guard lk(booContext->m_callbackMutex); if (booContext->m_callback) { boo::ITextInputCallback* textCb = booContext->m_callback->getTextInputCallback(); @@ -560,6 +568,7 @@ IGraphicsContext* _GraphicsContextCocoaMetalNew(IGraphicsContext::EGraphicsAPI a - (NSAttributedString*)attributedSubstringForProposedRange:(NSRange)aRange actualRange:(NSRangePointer)actualRange { + std::lock_guard lk(booContext->m_callbackMutex); if (booContext->m_callback) { boo::ITextInputCallback* textCb = booContext->m_callback->getTextInputCallback(); @@ -581,6 +590,7 @@ IGraphicsContext* _GraphicsContextCocoaMetalNew(IGraphicsContext::EGraphicsAPI a - (void)insertText:(id)aString replacementRange:(NSRange)replacementRange { + std::lock_guard lk(booContext->m_callbackMutex); if (booContext->m_callback) { boo::ITextInputCallback* textCb = booContext->m_callback->getTextInputCallback(); @@ -598,6 +608,7 @@ IGraphicsContext* _GraphicsContextCocoaMetalNew(IGraphicsContext::EGraphicsAPI a - (NSUInteger)characterIndexForPoint:(NSPoint)aPoint { + std::lock_guard lk(booContext->m_callbackMutex); if (booContext->m_callback) { boo::ITextInputCallback* textCb = booContext->m_callback->getTextInputCallback(); @@ -616,6 +627,7 @@ IGraphicsContext* _GraphicsContextCocoaMetalNew(IGraphicsContext::EGraphicsAPI a - (NSRect)firstRectForCharacterRange:(NSRange)aRange actualRange:(NSRangePointer)actualRange { + std::lock_guard lk(booContext->m_callbackMutex); if (booContext->m_callback) { boo::ITextInputCallback* textCb = booContext->m_callback->getTextInputCallback(); @@ -666,6 +678,7 @@ static inline boo::EMouseButton getButton(NSEvent* event) - (void)mouseDown:(NSEvent*)theEvent { + std::lock_guard lk(booContext->m_callbackMutex); if (!booContext->m_callback) return; NSPoint liw = [parentView convertPoint:[theEvent locationInWindow] fromView:nil]; @@ -684,6 +697,7 @@ static inline boo::EMouseButton getButton(NSEvent* event) - (void)mouseUp:(NSEvent*)theEvent { + std::lock_guard lk(booContext->m_callbackMutex); if (!booContext->m_callback) return; NSPoint liw = [parentView convertPoint:[theEvent locationInWindow] fromView:nil]; @@ -702,6 +716,7 @@ static inline boo::EMouseButton getButton(NSEvent* event) - (void)rightMouseDown:(NSEvent*)theEvent { + std::lock_guard lk(booContext->m_callbackMutex); if (!booContext->m_callback) return; NSPoint liw = [parentView convertPoint:[theEvent locationInWindow] fromView:nil]; @@ -720,6 +735,7 @@ static inline boo::EMouseButton getButton(NSEvent* event) - (void)rightMouseUp:(NSEvent*)theEvent { + std::lock_guard lk(booContext->m_callbackMutex); if (!booContext->m_callback) return; NSPoint liw = [parentView convertPoint:[theEvent locationInWindow] fromView:nil]; @@ -738,6 +754,7 @@ static inline boo::EMouseButton getButton(NSEvent* event) - (void)otherMouseDown:(NSEvent*)theEvent { + std::lock_guard lk(booContext->m_callbackMutex); if (!booContext->m_callback) return; boo::EMouseButton button = getButton(theEvent); @@ -758,6 +775,7 @@ static inline boo::EMouseButton getButton(NSEvent* event) - (void)otherMouseUp:(NSEvent*)theEvent { + std::lock_guard lk(booContext->m_callbackMutex); if (!booContext->m_callback) return; boo::EMouseButton button = getButton(theEvent); @@ -778,6 +796,7 @@ static inline boo::EMouseButton getButton(NSEvent* event) - (void)mouseMoved:(NSEvent*)theEvent { + std::lock_guard lk(booContext->m_callbackMutex); if (!booContext->m_callback) return; NSPoint liw = [parentView convertPoint:[theEvent locationInWindow] fromView:nil]; @@ -813,6 +832,7 @@ static inline boo::EMouseButton getButton(NSEvent* event) - (void)mouseEntered:(NSEvent*)theEvent { + std::lock_guard lk(booContext->m_callbackMutex); if (!booContext->m_callback) return; NSPoint liw = [parentView convertPoint:[theEvent locationInWindow] fromView:nil]; @@ -829,6 +849,7 @@ static inline boo::EMouseButton getButton(NSEvent* event) - (void)mouseExited:(NSEvent*)theEvent { + std::lock_guard lk(booContext->m_callbackMutex); if (!booContext->m_callback) return; NSPoint liw = [parentView convertPoint:[theEvent locationInWindow] fromView:nil]; @@ -845,6 +866,7 @@ static inline boo::EMouseButton getButton(NSEvent* event) - (void)scrollWheel:(NSEvent*)theEvent { + std::lock_guard lk(booContext->m_callbackMutex); if (!booContext->m_callback) return; NSPoint liw = [parentView convertPoint:[theEvent locationInWindow] fromView:nil]; @@ -867,6 +889,7 @@ static inline boo::EMouseButton getButton(NSEvent* event) - (void)touchesBeganWithEvent:(NSEvent*)event { + std::lock_guard lk(booContext->m_callbackMutex); if (!booContext->m_callback) return; for (NSTouch* touch in [event touchesMatchingPhase:NSTouchPhaseBegan inView:nil]) @@ -882,6 +905,7 @@ static inline boo::EMouseButton getButton(NSEvent* event) - (void)touchesEndedWithEvent:(NSEvent*)event { + std::lock_guard lk(booContext->m_callbackMutex); if (!booContext->m_callback) return; for (NSTouch* touch in [event touchesMatchingPhase:NSTouchPhaseEnded inView:nil]) @@ -897,6 +921,7 @@ static inline boo::EMouseButton getButton(NSEvent* event) - (void)touchesMovedWithEvent:(NSEvent*)event { + std::lock_guard lk(booContext->m_callbackMutex); if (!booContext->m_callback) return; for (NSTouch* touch in [event touchesMatchingPhase:NSTouchPhaseMoved inView:nil]) @@ -912,6 +937,7 @@ static inline boo::EMouseButton getButton(NSEvent* event) - (void)touchesCancelledWithEvent:(NSEvent*)event { + std::lock_guard lk(booContext->m_callbackMutex); if (!booContext->m_callback) return; for (NSTouch* touch in [event touchesMatchingPhase:NSTouchPhaseCancelled inView:nil]) @@ -1035,6 +1061,7 @@ static boo::ESpecialKey translateKeycode(short code) - (void)keyDown:(NSEvent*)theEvent { + std::lock_guard lk(booContext->m_callbackMutex); if (!booContext->m_callback) return; boo::ESpecialKey special = translateKeycode(theEvent.keyCode); @@ -1057,6 +1084,7 @@ static boo::ESpecialKey translateKeycode(short code) - (void)keyUp:(NSEvent*)theEvent { + std::lock_guard lk(booContext->m_callbackMutex); if (!booContext->m_callback) return; boo::ESpecialKey special = translateKeycode(theEvent.keyCode); @@ -1077,6 +1105,7 @@ static boo::ESpecialKey translateKeycode(short code) - (void)flagsChanged:(NSEvent*)theEvent { + std::lock_guard lk(booContext->m_callbackMutex); if (!booContext->m_callback) return; NSUInteger modFlags = theEvent.modifierFlags; @@ -1147,6 +1176,7 @@ static boo::ESpecialKey translateKeycode(short code) - (void)reshape { + std::lock_guard lk(resp->booContext->m_callbackMutex); NSRect frame = [self convertRectToBacking:self.frame]; boo::SWindowRect rect = {int(frame.origin.x), int(frame.origin.y), int(frame.size.width), int(frame.size.height)}; @@ -1223,6 +1253,7 @@ static boo::ESpecialKey translateKeycode(short code) - (void)reshapeHandler { + std::lock_guard lk1(resp->booContext->m_callbackMutex); NSRect frame = [self convertRectToBacking:self.frame]; boo::SWindowRect rect = {int(frame.origin.x), int(frame.origin.y), int(frame.size.width), int(frame.size.height)}; diff --git a/lib/win/ApplicationWin32.cpp b/lib/win/ApplicationWin32.cpp index 545ff72..1c9ebbd 100644 --- a/lib/win/ApplicationWin32.cpp +++ b/lib/win/ApplicationWin32.cpp @@ -270,6 +270,11 @@ public: sampDesc.AddressW = D3D11_TEXTURE_ADDRESS_BORDER; m_3dCtx.m_ctx11.m_dev->CreateSamplerState(&sampDesc, &m_3dCtx.m_ctx11.m_ss[1]); + sampDesc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP; + sampDesc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP; + sampDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP; + m_3dCtx.m_ctx11.m_dev->CreateSamplerState(&sampDesc, &m_3dCtx.m_ctx11.m_ss[2]); + Log.report(logvisor::Info, "initialized D3D11 renderer"); return; } diff --git a/lib/win/WinCommon.hpp b/lib/win/WinCommon.hpp index 7786748..b02f4fd 100644 --- a/lib/win/WinCommon.hpp +++ b/lib/win/WinCommon.hpp @@ -51,7 +51,7 @@ struct D3D11Context ComPtr m_dxFactory; ComPtr m_dev; ComPtr m_devCtx; - ComPtr m_ss[2]; + ComPtr m_ss[3]; struct Window { ComPtr m_swapChain;