summaryrefslogtreecommitdiff
path: root/tools/gfx/open-gl/render-gl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tools/gfx/open-gl/render-gl.cpp')
-rw-r--r--tools/gfx/open-gl/render-gl.cpp614
1 files changed, 515 insertions, 99 deletions
diff --git a/tools/gfx/open-gl/render-gl.cpp b/tools/gfx/open-gl/render-gl.cpp
index 4251abe98..34ea70eef 100644
--- a/tools/gfx/open-gl/render-gl.cpp
+++ b/tools/gfx/open-gl/render-gl.cpp
@@ -3,13 +3,11 @@
#include "../nvapi/nvapi-util.h"
-//WORKING:#include "options.h"
#include "../renderer-shared.h"
#include "../render-graphics-common.h"
-#include <stdio.h>
-#include <stdlib.h>
#include "core/slang-basic.h"
+#include "core/slang-blob.h"
#include "core/slang-secure-crt.h"
#include "external/stb/stb_image_write.h"
@@ -33,6 +31,7 @@
#include <GL/GL.h>
#include "external/glext.h"
+#include "external/wglext.h"
// We define an "X-macro" for mapping over loadable OpenGL
// extension entry point that we will use, so that we can
@@ -69,8 +68,21 @@
F(glBindSampler, PFNGLBINDSAMPLERPROC) \
F(glTexImage3D, PFNGLTEXIMAGE3DPROC) \
F(glSamplerParameteri, PFNGLSAMPLERPARAMETERIPROC) \
+ F(glGenFramebuffers, PFNGLGENFRAMEBUFFERSPROC) \
+ F(glDeleteFramebuffers, PFNGLDELETEFRAMEBUFFERSPROC) \
+ F(glBindFramebuffer, PFNGLBINDFRAMEBUFFERPROC) \
+ F(glFramebufferTexture2D, PFNGLFRAMEBUFFERTEXTURE2DPROC) \
+ F(glFramebufferTextureLayer, PFNGLFRAMEBUFFERTEXTURELAYERPROC) \
+ F(glBlitFramebuffer, PFNGLBLITFRAMEBUFFERPROC) \
+ F(glCheckFramebufferStatus, PFNGLCHECKFRAMEBUFFERSTATUSPROC) \
+ F(glGenVertexArrays, PFNGLGENVERTEXARRAYSPROC) \
+ F(glBindVertexArray, PFNGLBINDVERTEXARRAYPROC) \
+ F(glDeleteVertexArrays, PFNGLDELETEVERTEXARRAYSPROC) \
/* end */
+#define MAP_WGL_EXTENSION_FUNCS(F) \
+ F(wglCreateContextAttribsARB, PFNWGLCREATECONTEXTATTRIBSARBPROC) \
+ /* end */
using namespace Slang;
namespace gfx {
@@ -78,13 +90,24 @@ namespace gfx {
class GLRenderer : public GraphicsAPIRenderer
{
public:
-
// Renderer implementation
- virtual SLANG_NO_THROW SlangResult SLANG_MCALL initialize(const Desc& desc, void* inWindowHandle) override;
+ virtual SLANG_NO_THROW SlangResult SLANG_MCALL initialize(const Desc& desc) override;
virtual SLANG_NO_THROW void SLANG_MCALL setClearColor(const float color[4]) override;
virtual SLANG_NO_THROW void SLANG_MCALL clearFrame() override;
- virtual SLANG_NO_THROW void SLANG_MCALL presentFrame() override;
- virtual SLANG_NO_THROW ITextureResource::Desc SLANG_MCALL getSwapChainTextureDesc() override;
+ virtual SLANG_NO_THROW void SLANG_MCALL beginFrame() override;
+ virtual SLANG_NO_THROW void SLANG_MCALL endFrame() override;
+ virtual SLANG_NO_THROW void SLANG_MCALL
+ makeSwapchainImagePresentable(ISwapchain* swapchain) override
+ {
+ SLANG_UNUSED(swapchain);
+ }
+ virtual SLANG_NO_THROW Result SLANG_MCALL createSwapchain(
+ const ISwapchain::Desc& desc, WindowHandle window, ISwapchain** outSwapchain) override;
+ virtual SLANG_NO_THROW Result SLANG_MCALL createFramebufferLayout(
+ const IFramebufferLayout::Desc& desc, IFramebufferLayout** outLayout) override;
+ virtual SLANG_NO_THROW Result SLANG_MCALL
+ createFramebuffer(const IFramebuffer::Desc& desc, IFramebuffer** outFramebuffer) override;
+ virtual SLANG_NO_THROW void SLANG_MCALL setFramebuffer(IFramebuffer* frameBuffer) override;
virtual SLANG_NO_THROW Result SLANG_MCALL createTextureResource(
IResource::Usage initialUsage,
@@ -114,7 +137,7 @@ public:
virtual SLANG_NO_THROW Result SLANG_MCALL
createPipelineLayout(const IPipelineLayout::Desc& desc, IPipelineLayout** outLayout) override;
virtual SLANG_NO_THROW Result SLANG_MCALL
- createDescriptorSet(IDescriptorSetLayout* layout, IDescriptorSet** outDescriptorSet) override;
+ createDescriptorSet(IDescriptorSetLayout* layout, IDescriptorSet::Flag::Enum flag, IDescriptorSet** outDescriptorSet) override;
virtual SLANG_NO_THROW Result SLANG_MCALL
createProgram(const IShaderProgram::Desc& desc, IShaderProgram** outProgram) override;
@@ -123,8 +146,8 @@ public:
virtual SLANG_NO_THROW Result SLANG_MCALL createComputePipelineState(
const ComputePipelineStateDesc& desc, IPipelineState** outState) override;
- virtual SLANG_NO_THROW SlangResult SLANG_MCALL captureScreenSurface(
- void* buffer, size_t* inOutBufferSize, size_t* outRowPitch, size_t* outPixelSize) override;
+ virtual SLANG_NO_THROW SlangResult SLANG_MCALL readTextureResource(
+ ITextureResource* texture, ISlangBlob** outBlob, size_t* outRowPitch, size_t* outPixelSize) override;
virtual SLANG_NO_THROW void* SLANG_MCALL map(IBufferResource* buffer, MapFlavor flavor) override;
virtual SLANG_NO_THROW void SLANG_MCALL unmap(IBufferResource* buffer) override;
@@ -146,8 +169,6 @@ public:
virtual SLANG_NO_THROW void SLANG_MCALL
setIndexBuffer(IBufferResource* buffer, Format indexFormat, UInt offset) override;
virtual SLANG_NO_THROW void SLANG_MCALL
- setDepthStencilTarget(IResourceView* depthStencilView) override;
- virtual SLANG_NO_THROW void SLANG_MCALL
setViewports(UInt count, Viewport const* viewports) override;
virtual SLANG_NO_THROW void SLANG_MCALL
setScissorRects(UInt count, ScissorRect const* rects) override;
@@ -166,6 +187,7 @@ public:
{
return m_currentPipelineState.Ptr();
}
+ HGLRC createGLContext(HDC hdc);
GLRenderer();
~GLRenderer();
@@ -298,6 +320,200 @@ public:
GLuint m_bufferID;
};
+ class FramebufferLayoutImpl
+ : public IFramebufferLayout
+ , public RefObject
+ {
+ public:
+ SLANG_REF_OBJECT_IUNKNOWN_ALL
+ IFramebufferLayout* getInterface(const Guid& guid)
+ {
+ if (guid == GfxGUID::IID_ISlangUnknown || guid == GfxGUID::IID_IFramebufferLayout)
+ return static_cast<IFramebufferLayout*>(this);
+ return nullptr;
+ }
+
+ public:
+ ShortList<IFramebufferLayout::AttachmentLayout> m_renderTargets;
+ bool m_hasDepthStencil = false;
+ IFramebufferLayout::AttachmentLayout m_depthStencil;
+ };
+
+ class FramebufferImpl
+ : public IFramebuffer
+ , public RefObject
+ {
+ public:
+ SLANG_REF_OBJECT_IUNKNOWN_ALL
+ IFramebuffer* getInterface(const Guid& guid)
+ {
+ if (guid == GfxGUID::IID_ISlangUnknown || guid == GfxGUID::IID_IFramebuffer)
+ return static_cast<IFramebuffer*>(this);
+ return nullptr;
+ }
+
+ public:
+ GLuint m_framebuffer;
+ WeakSink<GLRenderer>* m_renderer;
+ ShortList<RefPtr<TextureViewImpl>> renderTargetViews;
+ RefPtr<TextureViewImpl> depthStencilView;
+ FramebufferImpl(WeakSink<GLRenderer>* renderer) :m_renderer(renderer) {}
+ ~FramebufferImpl()
+ {
+ if (auto renderer = m_renderer->get())
+ {
+ renderer->glDeleteFramebuffers(1, &m_framebuffer);
+ }
+ }
+ void createGLFramebuffer()
+ {
+ auto renderer = m_renderer->get();
+ renderer->glGenFramebuffers(1, &m_framebuffer);
+ renderer->glBindFramebuffer(GL_FRAMEBUFFER, m_framebuffer);
+ for (Index i = 0; i < renderTargetViews.getCount(); i++)
+ {
+ auto rtv = renderTargetViews[i].Ptr();
+ renderer->glFramebufferTexture2D(
+ GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + (uint32_t)i, GL_TEXTURE_2D, rtv->m_textureID, 0);
+ }
+ if (depthStencilView)
+ {
+ renderer->glFramebufferTexture2D(
+ GL_FRAMEBUFFER,
+ GL_DEPTH_ATTACHMENT,
+ GL_TEXTURE_2D,
+ depthStencilView->m_textureID,
+ 0);
+ }
+ auto error = renderer->glCheckFramebufferStatus(GL_FRAMEBUFFER);
+ if (error != GL_FRAMEBUFFER_COMPLETE)
+ {
+ return;
+ }
+ }
+ };
+
+ class SwapchainImpl
+ : public ISwapchain
+ , public RefObject
+ {
+ public:
+ SLANG_REF_OBJECT_IUNKNOWN_ALL
+ ISwapchain* getInterface(const Guid& guid)
+ {
+ if (guid == GfxGUID::IID_ISlangUnknown || guid == GfxGUID::IID_ISwapchain)
+ return static_cast<ISwapchain*>(this);
+ return nullptr;
+ }
+
+ public:
+ ~SwapchainImpl()
+ {
+ for (auto image : m_images)
+ image->m_handle = 0;
+ if (auto rendererRef = m_renderer->get())
+ {
+ rendererRef->glDeleteFramebuffers(1, &m_framebuffer);
+ glDeleteTextures(1, &m_backBuffer);
+ }
+ wglMakeCurrent(m_hdc, 0);
+ wglDeleteContext(m_glrc);
+ ::ReleaseDC(m_hwnd, m_hdc);
+ }
+ Result init(GLRenderer* renderer, const ISwapchain::Desc& desc, WindowHandle window)
+ {
+ m_renderer = renderer->m_weakRenderer.Ptr();
+
+ m_hwnd = (HWND)window.handleValues[0];
+ m_hdc = ::GetDC(m_hwnd);
+ m_glrc = renderer->createGLContext(m_hdc);
+ wglMakeCurrent(renderer->m_hdc, renderer->m_glContext);
+
+ m_desc = desc;
+
+ glGenTextures(1, &m_backBuffer);
+ glBindTexture(GL_TEXTURE_2D, m_backBuffer);
+ glTexImage2D(
+ GL_TEXTURE_2D,
+ 0,
+ GL_RGBA8,
+ desc.width,
+ desc.height,
+ 0,
+ GL_RGBA,
+ GL_UNSIGNED_BYTE,
+ nullptr);
+
+ wglMakeCurrent(m_hdc, m_glrc);
+ renderer->glGenFramebuffers(1, &m_framebuffer);
+ renderer->glBindFramebuffer(GL_READ_FRAMEBUFFER, m_framebuffer);
+ renderer->glFramebufferTexture2D(
+ GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_backBuffer, 0);
+
+ for (uint32_t i = 0; i < desc.imageCount; i++)
+ {
+ ITextureResource::Desc texDesc = {};
+ texDesc.init2D(
+ IResource::Type::Texture2D,
+ gfx::Format::RGBA_Unorm_UInt8,
+ desc.width,
+ desc.height,
+ 1);
+ RefPtr<TextureResourceImpl> tex =
+ new TextureResourceImpl(IResource::Usage::RenderTarget, texDesc, m_renderer);
+ tex->m_handle = m_backBuffer;
+ m_images.add(tex);
+ }
+ wglMakeCurrent(renderer->m_hdc, renderer->m_glContext);
+ return SLANG_OK;
+ }
+ virtual SLANG_NO_THROW const Desc& SLANG_MCALL getDesc() override { return m_desc; }
+ virtual SLANG_NO_THROW Result
+ getImage(uint32_t index, ITextureResource** outResource) override
+ {
+ m_images[index]->addRef();
+ *outResource = m_images[index].Ptr();
+ return SLANG_OK;
+ }
+ virtual SLANG_NO_THROW Result present() override
+ {
+ glFlush();
+ wglMakeCurrent(m_hdc, m_glrc);
+ auto renderer = m_renderer->get();
+ renderer->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
+ renderer->glBindFramebuffer(GL_READ_FRAMEBUFFER, m_framebuffer);
+ renderer->glBlitFramebuffer(
+ 0,
+ 0,
+ m_desc.width,
+ m_desc.height,
+ 0,
+ 0,
+ m_desc.width,
+ m_desc.height,
+ GL_COLOR_BUFFER_BIT,
+ GL_NEAREST);
+ SwapBuffers(m_hdc);
+ wglMakeCurrent(renderer->m_hdc, renderer->m_glContext);
+ return SLANG_OK;
+ }
+
+ virtual SLANG_NO_THROW uint32_t acquireNextImage() override
+ {
+ return 0;
+ }
+
+ public:
+ WeakSink<GLRenderer>* m_renderer = nullptr;
+ GLuint m_framebuffer;
+ GLuint m_backBuffer;
+ HGLRC m_glrc;
+ HWND m_hwnd;
+ HDC m_hdc;
+ ISwapchain::Desc m_desc;
+ ShortList<RefPtr<TextureResourceImpl>> m_images;
+ };
+
enum class GLDescriptorSlotType
{
ConstantBuffer,
@@ -429,6 +645,8 @@ public:
{
Unknown,
RGBA_Unorm_UInt8,
+ D_Float32,
+ D_Unorm24_S8,
CountOf,
};
@@ -455,10 +673,11 @@ public:
static void compileTimeAsserts();
HDC m_hdc;
- HGLRC m_glContext;
+ HGLRC m_glContext = 0;
float m_clearColor[4] = { 0, 0, 0, 0 };
-
+ GLuint m_vao;
RefPtr<PipelineStateImpl> m_currentPipelineState;
+ RefPtr<FramebufferImpl> m_currentFramebuffer;
RefPtr<WeakSink<GLRenderer> > m_weakRenderer;
RefPtr<DescriptorSetImpl> m_boundDescriptorSets[kMaxDescriptorSetCount];
@@ -469,11 +688,12 @@ public:
UInt m_boundVertexStreamOffsets[kMaxVertexStreams];
Desc m_desc;
-
+ WindowHandle m_windowHandle;
// Declare a function pointer for each OpenGL
// extension function we need to load
#define DECLARE_GL_EXTENSION_FUNC(NAME, TYPE) TYPE NAME;
MAP_GL_EXTENSION_FUNCS(DECLARE_GL_EXTENSION_FUNC)
+ MAP_WGL_EXTENSION_FUNCS(DECLARE_GL_EXTENSION_FUNC)
#undef DECLARE_GL_EXTENSION_FUNC
static const GlPixelFormatInfo s_pixelFormatInfos[]; /// Maps GlPixelFormat to a format info
@@ -484,6 +704,9 @@ public:
switch (format)
{
case Format::RGBA_Unorm_UInt8: return GlPixelFormat::RGBA_Unorm_UInt8;
+ case Format::D_Float32: return GlPixelFormat::D_Float32;
+ case Format::D_Unorm24_S8: return GlPixelFormat::D_Unorm24_S8;
+
default: return GlPixelFormat::Unknown;
}
}
@@ -493,6 +716,9 @@ public:
// internalType, format, formatType
{ 0, 0, 0}, // GlPixelFormat::Unknown
{ GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE }, // GlPixelFormat::RGBA_Unorm_UInt8
+ { GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE}, // GlPixelFormat::D_Float32
+ { GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_BYTE}, // GlPixelFormat::D_Unorm24_S8
+
};
/* static */void GLRenderer::compileTimeAsserts()
@@ -500,10 +726,10 @@ public:
SLANG_COMPILE_TIME_ASSERT(SLANG_COUNT_OF(s_pixelFormatInfos) == int(GlPixelFormat::CountOf));
}
-SlangResult SLANG_MCALL createGLRenderer(const IRenderer::Desc* desc, void* windowHandle, IRenderer** outRenderer)
+SlangResult SLANG_MCALL createGLRenderer(const IRenderer::Desc* desc, IRenderer** outRenderer)
{
RefPtr<GLRenderer> result = new GLRenderer();
- SLANG_RETURN_ON_FAIL(result->initialize(*desc, windowHandle));
+ SLANG_RETURN_ON_FAIL(result->initialize(*desc));
*outRenderer = result.detach();
return SLANG_OK;
}
@@ -523,26 +749,6 @@ void GLRenderer::debugCallback(GLenum source, GLenum type, GLuint id, GLenum sev
}
}
-
-GLRenderer::GLRenderer()
-{
- m_weakRenderer = new WeakSink<GLRenderer>(this);
-}
-
-GLRenderer::~GLRenderer()
-{
- // We can destroy things whilst in this state
- m_currentPipelineState.setNull();
-
- // By resetting the weak pointer, other objects accessing through WeakSink<GLRenderer> will no longer
- // be able to access this object which is entering a 'being destroyed' to 'destroyed' state
- if (m_weakRenderer)
- {
- SLANG_ASSERT(m_weakRenderer->get() == this);
- m_weakRenderer->detach();
- }
-}
-
/* static */void APIENTRY GLRenderer::staticDebugCallback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* message, const void* userParam)
{
((GLRenderer*)userParam)->debugCallback(source, type, id, severity, length, message);
@@ -582,6 +788,11 @@ void GLRenderer::bindBufferImpl(int target, UInt startSlot, UInt slotCount, Buff
void GLRenderer::flushStateForDraw()
{
+ if (m_currentFramebuffer)
+ {
+ glBindFramebuffer(GL_FRAMEBUFFER, m_currentFramebuffer->m_framebuffer);
+ }
+ glBindVertexArray(m_vao);
auto inputLayout = m_currentPipelineState->m_inputLayout.Ptr();
auto attrCount = Index(inputLayout->m_attributeCount);
for (Index ii = 0; ii < attrCount; ++ii)
@@ -606,7 +817,6 @@ void GLRenderer::flushStateForDraw()
{
glDisableVertexAttribArray((GLuint)ii);
}
-
// Next bind the descriptor sets as required by the layout
auto pipelineLayout = m_currentPipelineState->m_pipelineLayout;
auto descriptorSetCount = pipelineLayout->m_sets.getCount();
@@ -770,36 +980,126 @@ GLuint GLRenderer::loadShader(GLenum stage, const char* source)
return shaderID;
}
-#if 0
-void GLRenderer::destroyBindingEntries(const BindingState::Desc& desc, const BindingDetail* details)
+// !!!!!!!!!!!!!!!!!!!!!!!!!!!! Renderer interface !!!!!!!!!!!!!!!!!!!!!!!!!!
+
+#ifdef _WIN32
+LRESULT CALLBACK WindowProc(_In_ HWND hwnd, _In_ UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam)
{
- const auto& bindings = desc.m_bindings;
- const int numBindings = int(bindings.Count());
- for (int i = 0; i < numBindings; ++i)
- {
- const auto& binding = bindings[i];
- const auto& detail = details[i];
+ return DefWindowProc(hwnd, uMsg, wParam, lParam);
+}
+#endif
- if (binding.bindingType == BindingType::Sampler && detail.m_samplerHandle != 0)
- {
- glDeleteSamplers(1, &detail.m_samplerHandle);
- }
- }
+WindowHandle createWindow()
+{
+ WindowHandle window = {};
+#ifdef _WIN32
+ const wchar_t className[] = L"OpenGLContextWindow";
+ static bool windowClassRegistered = false;
+ HINSTANCE hInstance = GetModuleHandle(NULL);
+ if (!windowClassRegistered)
+ {
+ windowClassRegistered = true;
+ WNDCLASS wc = {};
+ wc.lpfnWndProc = WindowProc;
+ wc.hInstance = hInstance;
+ wc.lpszClassName = className;
+ RegisterClass(&wc);
+ }
+
+ HWND hwnd = CreateWindowEx(
+ 0, // Optional window styles.
+ className, // Window class
+ L"GLWindow", // Window text
+ WS_OVERLAPPEDWINDOW, // Window style
+ // Size and position
+ CW_USEDEFAULT,
+ CW_USEDEFAULT,
+ CW_USEDEFAULT,
+ CW_USEDEFAULT,
+ NULL, // Parent window
+ NULL, // Menu
+ hInstance, // Instance handle
+ NULL // Additional application data
+ );
+
+ if (hwnd == NULL)
+ {
+ return window;
+ }
+ window = WindowHandle::FromHwnd(hwnd);
+#endif
+ return window;
}
+
+void destroyWindow(WindowHandle window)
+{
+#ifdef _WIN32
+ DestroyWindow((HWND)window.handleValues[0]);
#endif
+}
-// !!!!!!!!!!!!!!!!!!!!!!!!!!!! Renderer interface !!!!!!!!!!!!!!!!!!!!!!!!!!
+GLRenderer::GLRenderer() { m_weakRenderer = new WeakSink<GLRenderer>(this); }
-SLANG_NO_THROW Result SLANG_MCALL GLRenderer::initialize(const Desc& desc, void* inWindowHandle)
+GLRenderer::~GLRenderer()
+{
+ // We can destroy things whilst in this state
+ m_currentPipelineState.setNull();
+ m_currentFramebuffer.setNull();
+ if (glDeleteVertexArrays)
+ {
+ glDeleteVertexArrays(1, &m_vao);
+ }
+ if (m_glContext)
+ {
+ wglDeleteContext(m_glContext);
+ }
+ destroyWindow(m_windowHandle);
+
+ // By resetting the weak pointer, other objects accessing through WeakSink<GLRenderer> will no
+ // longer be able to access this object which is entering a 'being destroyed' to 'destroyed'
+ // state
+ if (m_weakRenderer)
+ {
+ SLANG_ASSERT(m_weakRenderer->get() == this);
+ m_weakRenderer->detach();
+ }
+}
+
+HGLRC GLRenderer::createGLContext(HDC hdc)
+{
+ PIXELFORMATDESCRIPTOR pixelFormatDesc = {sizeof(PIXELFORMATDESCRIPTOR)};
+ pixelFormatDesc.nVersion = 1;
+ pixelFormatDesc.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
+ pixelFormatDesc.iPixelType = PFD_TYPE_RGBA;
+ pixelFormatDesc.cColorBits = 32;
+ pixelFormatDesc.cDepthBits = 24;
+ pixelFormatDesc.cStencilBits = 8;
+ pixelFormatDesc.iLayerType = PFD_MAIN_PLANE;
+ int pixelFormatIndex = ChoosePixelFormat(hdc, &pixelFormatDesc);
+ SetPixelFormat(hdc, pixelFormatIndex, &pixelFormatDesc);
+
+ int attributeList[5];
+
+ attributeList[0] = WGL_CONTEXT_MAJOR_VERSION_ARB;
+ attributeList[1] = 4;
+ attributeList[2] = WGL_CONTEXT_MINOR_VERSION_ARB;
+ attributeList[3] = 3;
+ attributeList[4] = 0;
+
+ HGLRC newGLContext = wglCreateContextAttribsARB(hdc, m_glContext, attributeList);
+ return newGLContext;
+}
+
+SLANG_NO_THROW Result SLANG_MCALL GLRenderer::initialize(const Desc& desc)
{
SLANG_RETURN_ON_FAIL(slangContext.initialize(desc.slang, SLANG_GLSL, "glsl_440"));
- SLANG_RETURN_ON_FAIL(GraphicsAPIRenderer::initialize(desc, inWindowHandle));
+ SLANG_RETURN_ON_FAIL(GraphicsAPIRenderer::initialize(desc));
- auto windowHandle = (HWND)inWindowHandle;
+ m_windowHandle = createWindow();
m_desc = desc;
- m_hdc = ::GetDC(windowHandle);
+ m_hdc = ::GetDC((HWND)m_windowHandle.handleValues[0]);
PIXELFORMATDESCRIPTOR pixelFormatDesc = { sizeof(PIXELFORMATDESCRIPTOR) };
pixelFormatDesc.nVersion = 1;
@@ -812,7 +1112,6 @@ SLANG_NO_THROW Result SLANG_MCALL GLRenderer::initialize(const Desc& desc, void*
int pixelFormatIndex = ChoosePixelFormat(m_hdc, &pixelFormatDesc);
SetPixelFormat(m_hdc, pixelFormatIndex, &pixelFormatDesc);
-
m_glContext = wglCreateContext(m_hdc);
wglMakeCurrent(m_hdc, m_glContext);
@@ -844,19 +1143,39 @@ SLANG_NO_THROW Result SLANG_MCALL GLRenderer::initialize(const Desc& desc, void*
#define LOAD_GL_EXTENSION_FUNC(NAME, TYPE) NAME = (TYPE) wglGetProcAddress(#NAME);
MAP_GL_EXTENSION_FUNCS(LOAD_GL_EXTENSION_FUNC)
+ MAP_WGL_EXTENSION_FUNCS(LOAD_GL_EXTENSION_FUNC)
#undef LOAD_GL_EXTENSION_FUNC
+ wglMakeCurrent(m_hdc, 0);
+ wglDeleteContext(m_glContext);
+ m_glContext = 0;
+
+ if (!wglCreateContextAttribsARB)
+ {
+ return SLANG_FAIL;
+ }
+
+ m_glContext = createGLContext(m_hdc);
+
+ if (m_glContext == NULL)
+ {
+ return SLANG_FAIL;
+ }
+ wglMakeCurrent(m_hdc, m_glContext);
+
glDisable(GL_DEPTH_TEST);
glDisable(GL_CULL_FACE);
- glViewport(0, 0, desc.width, desc.height);
+ if (!glGenVertexArrays)
+ return SLANG_FAIL;
+
+ glGenVertexArrays(1, &m_vao);
if (glDebugMessageCallback)
{
glEnable(GL_DEBUG_OUTPUT);
glDebugMessageCallback(staticDebugCallback, this);
}
-
return SLANG_OK;
}
@@ -870,49 +1189,97 @@ SLANG_NO_THROW void SLANG_MCALL GLRenderer::clearFrame()
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
}
-SLANG_NO_THROW void SLANG_MCALL GLRenderer::presentFrame()
+SLANG_NO_THROW void SLANG_MCALL GLRenderer::beginFrame() { }
+
+SLANG_NO_THROW void SLANG_MCALL GLRenderer::endFrame()
{
glFlush();
- ::SwapBuffers(m_hdc);
}
-SLANG_NO_THROW TextureResource::Desc SLANG_MCALL GLRenderer::getSwapChainTextureDesc()
+SLANG_NO_THROW Result SLANG_MCALL GLRenderer::createSwapchain(
+ const ISwapchain::Desc& desc, WindowHandle window, ISwapchain** outSwapchain)
{
- TextureResource::Desc desc;
- desc.init2D(IResource::Type::Texture2D, Format::Unknown, m_desc.width, m_desc.height, 1);
- return desc;
+ RefPtr<SwapchainImpl> swapchain = new SwapchainImpl();
+ SLANG_RETURN_ON_FAIL(swapchain->init(this, desc, window));
+ *outSwapchain = swapchain.detach();
+ wglMakeCurrent(m_hdc, m_glContext);
+ return SLANG_OK;
}
-SLANG_NO_THROW Result SLANG_MCALL GLRenderer::captureScreenSurface(
- void* buffer, size_t* inOutBufferSize, size_t* outRowPitch, size_t* outPixelSize)
+SLANG_NO_THROW Result SLANG_MCALL GLRenderer::createFramebufferLayout(
+ const IFramebufferLayout::Desc& desc, IFramebufferLayout** outLayout)
{
- size_t requiredSize = m_desc.width * m_desc.height * sizeof(uint32_t);
- if (outRowPitch)
- *outRowPitch = m_desc.width * sizeof(uint32_t);
- if (outPixelSize)
- *outPixelSize = sizeof(uint32_t);
+ RefPtr<FramebufferLayoutImpl> layout = new FramebufferLayoutImpl();
+ layout->m_renderTargets.setCount(desc.renderTargetCount);
+ for (uint32_t i = 0; i < desc.renderTargetCount; i++)
+ {
+ layout->m_renderTargets[i] = desc.renderTargets[i];
+ }
- if (!buffer || *inOutBufferSize == 0)
+ if (desc.depthStencil)
{
- *inOutBufferSize = requiredSize;
- return SLANG_OK;
+ layout->m_hasDepthStencil = true;
+ layout->m_depthStencil = *desc.depthStencil;
+ }
+ else
+ {
+ layout->m_hasDepthStencil = false;
+ }
+ *outLayout = layout.detach();
+ return SLANG_OK;
+}
+
+SLANG_NO_THROW Result SLANG_MCALL
+ GLRenderer::createFramebuffer(const IFramebuffer::Desc& desc, IFramebuffer** outFramebuffer)
+{
+ RefPtr<FramebufferImpl> framebuffer = new FramebufferImpl(m_weakRenderer);
+ framebuffer->renderTargetViews.setCount(desc.renderTargetCount);
+ for (uint32_t i = 0; i < desc.renderTargetCount; i++)
+ {
+ framebuffer->renderTargetViews[i] =
+ static_cast<TextureViewImpl*>(desc.renderTargetViews[i]);
}
- if (*inOutBufferSize < requiredSize)
- return SLANG_ERROR_INSUFFICIENT_BUFFER;
+ framebuffer->depthStencilView = static_cast<TextureViewImpl*>(desc.depthStencilView);
+ framebuffer->createGLFramebuffer();
+ *outFramebuffer = framebuffer.detach();
+ return SLANG_OK;
+}
- glReadPixels(0, 0, m_desc.width, m_desc.height, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
+SLANG_NO_THROW void SLANG_MCALL GLRenderer::setFramebuffer(IFramebuffer* frameBuffer)
+{
+ m_currentFramebuffer = static_cast<FramebufferImpl*>(frameBuffer);
+}
+
+SLANG_NO_THROW Result SLANG_MCALL GLRenderer::readTextureResource(
+ ITextureResource* texture, ISlangBlob** outBlob, size_t* outRowPitch, size_t* outPixelSize)
+{
+ auto resource = static_cast<TextureResourceImpl*>(texture);
+ auto size = resource->getDesc()->size;
+ size_t requiredSize = size.width * size.height * sizeof(uint32_t);
+ if (outRowPitch)
+ *outRowPitch = size.width * sizeof(uint32_t);
+ if (outPixelSize)
+ *outPixelSize = sizeof(uint32_t);
+
+ RefPtr<ListBlob> blob = new ListBlob();
+ blob->m_data.setCount(requiredSize);
+ auto buffer = blob->m_data.begin();
+ glBindTexture(resource->m_target, resource->m_handle);
+ glGetTexImage(resource->m_target, 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
// Flip pixels vertically in-place.
- for (int y = 0; y < m_desc.height / 2; y++)
+ for (int y = 0; y < size.height / 2; y++)
{
- for (int x = 0; x < m_desc.width; x++)
+ for (int x = 0; x < size.width; x++)
{
std::swap(
- *((uint32_t*)buffer + y * m_desc.width + x),
- *((uint32_t*)buffer + (m_desc.height - y - 1) * m_desc.width + x));
+ *((uint32_t*)buffer + y * size.width + x),
+ *((uint32_t*)buffer + (size.height - y - 1) * size.width + x));
}
}
+ *outBlob = blob.detach();
+
return SLANG_OK;
}
@@ -945,12 +1312,8 @@ SLANG_NO_THROW Result SLANG_MCALL GLRenderer::createTextureResource(
const int effectiveArraySize = srcDesc.calcEffectiveArraySize();
- assert(initData);
- assert(initData->numSubResources == srcDesc.numMipLevels * srcDesc.size.depth * effectiveArraySize);
-
// Set on texture so will be freed if failure
texture->m_handle = handle;
- const void*const*const data = initData->subResources;
switch (srcDesc.type)
{
@@ -966,7 +1329,16 @@ SLANG_NO_THROW Result SLANG_MCALL GLRenderer::createTextureResource(
{
for (int j = 0; j < srcDesc.numMipLevels; j++)
{
- glTexImage2D(target, j, internalFormat, srcDesc.size.width, i, 0, format, formatType, data[slice++]);
+ glTexImage2D(
+ target,
+ j,
+ internalFormat,
+ Math::Max(1, srcDesc.size.width >> j),
+ i,
+ 0,
+ format,
+ formatType,
+ initData ? initData->subResources[slice++] : nullptr);
}
}
}
@@ -976,7 +1348,15 @@ SLANG_NO_THROW Result SLANG_MCALL GLRenderer::createTextureResource(
glBindTexture(target, handle);
for (int i = 0; i < srcDesc.numMipLevels; i++)
{
- glTexImage1D(target, i, internalFormat, srcDesc.size.width, 0, format, formatType, data[i]);
+ glTexImage1D(
+ target,
+ i,
+ internalFormat,
+ Math::Max(1, srcDesc.size.width >> i),
+ 0,
+ format,
+ formatType,
+ initData ? initData->subResources[i] : nullptr);
}
}
break;
@@ -1002,7 +1382,17 @@ SLANG_NO_THROW Result SLANG_MCALL GLRenderer::createTextureResource(
{
for (int j = 0; j < srcDesc.numMipLevels; j++)
{
- glTexImage3D(target, j, internalFormat, srcDesc.size.width, srcDesc.size.height, slice, 0, format, formatType, data[slice++]);
+ glTexImage3D(
+ target,
+ j,
+ internalFormat,
+ Math::Max(1, srcDesc.size.width >> j),
+ Math::Max(1, srcDesc.size.height >> j),
+ slice,
+ 0,
+ format,
+ formatType,
+ initData ? initData->subResources[slice++] : nullptr);
}
}
}
@@ -1018,7 +1408,16 @@ SLANG_NO_THROW Result SLANG_MCALL GLRenderer::createTextureResource(
{
for (int i = 0; i < srcDesc.numMipLevels; i++)
{
- glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + j, i, internalFormat, srcDesc.size.width, srcDesc.size.height, 0, format, formatType, data[slice++]);
+ glTexImage2D(
+ GL_TEXTURE_CUBE_MAP_POSITIVE_X + j,
+ i,
+ internalFormat,
+ Math::Max(1, srcDesc.size.width >> i),
+ Math::Max(1, srcDesc.size.height >> i),
+ 0,
+ format,
+ formatType,
+ initData ? initData->subResources[slice++] : nullptr);
}
}
}
@@ -1028,7 +1427,16 @@ SLANG_NO_THROW Result SLANG_MCALL GLRenderer::createTextureResource(
glBindTexture(target, handle);
for (int i = 0; i < srcDesc.numMipLevels; i++)
{
- glTexImage2D(target, i, internalFormat, srcDesc.size.width, srcDesc.size.height, 0, format, formatType, data[i]);
+ glTexImage2D(
+ target,
+ i,
+ internalFormat,
+ Math::Max(1, srcDesc.size.width >> i),
+ Math::Max(1, srcDesc.size.height >> i),
+ 0,
+ format,
+ formatType,
+ initData ? initData->subResources[i] : nullptr);
}
}
}
@@ -1040,7 +1448,17 @@ SLANG_NO_THROW Result SLANG_MCALL GLRenderer::createTextureResource(
glBindTexture(target, handle);
for (int i = 0; i < srcDesc.numMipLevels; i++)
{
- glTexImage3D(target, i, internalFormat, srcDesc.size.width, srcDesc.size.height, srcDesc.size.depth, 0, format, formatType, data[i]);
+ glTexImage3D(
+ target,
+ i,
+ internalFormat,
+ Math::Max(1, srcDesc.size.width >> i),
+ Math::Max(1, srcDesc.size.height >> i),
+ Math::Max(1, srcDesc.size.depth >> i),
+ 0,
+ format,
+ formatType,
+ initData ? initData->subResources[i] : nullptr);
}
break;
}
@@ -1122,14 +1540,14 @@ SLANG_NO_THROW Result SLANG_MCALL
SLANG_NO_THROW Result SLANG_MCALL GLRenderer::createTextureView(
ITextureResource* texture, IResourceView::Desc const& desc, IResourceView** outView)
{
- auto resourceImpl = (TextureResourceImpl*) texture;
+ auto resourceImpl = static_cast<TextureResourceImpl*>(texture);
// TODO: actually do something?
RefPtr<TextureViewImpl> viewImpl = new TextureViewImpl();
viewImpl->m_resource = resourceImpl;
viewImpl->m_textureID = resourceImpl->m_handle;
- *outView = viewImpl;
+ *outView = viewImpl.detach();
return SLANG_OK;
}
@@ -1235,10 +1653,6 @@ SLANG_NO_THROW void SLANG_MCALL
{
}
-SLANG_NO_THROW void SLANG_MCALL GLRenderer::setDepthStencilTarget(IResourceView* depthStencilView)
-{
-}
-
SLANG_NO_THROW void SLANG_MCALL GLRenderer::setViewports(UInt count, Viewport const* viewports)
{
assert(count == 1);
@@ -1455,8 +1869,10 @@ SLANG_NO_THROW Result SLANG_MCALL
}
SLANG_NO_THROW Result SLANG_MCALL
- GLRenderer::createDescriptorSet(IDescriptorSetLayout* layout, IDescriptorSet** outDescriptorSet)
+ GLRenderer::createDescriptorSet(IDescriptorSetLayout* layout, IDescriptorSet::Flag::Enum flag, IDescriptorSet** outDescriptorSet)
{
+ SLANG_UNUSED(flag);
+
auto layoutImpl = (DescriptorSetLayoutImpl*) layout;
RefPtr<DescriptorSetImpl> descriptorSetImpl = new DescriptorSetImpl();