diff options
| author | Tim Foley <tfoleyNV@users.noreply.github.com> | 2018-06-28 11:14:48 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2018-06-28 11:14:48 -0700 |
| commit | dfe13b54286b27dd15f591455bbb86b7798285c2 (patch) | |
| tree | 4a11f01feaae059b6c11bdfbe12a614228af6dd5 /tools/render-test/render-gl.cpp | |
| parent | 22033f06573f900dc030c487b2c30feddf3d8f16 (diff) | |
Share graphics API layer between tests/examples (#603)
The `render-test` project has an in-progress graphics API abstraction layer, and it makes sense to share this code with our examples rather than write a bunch of redundant code between examples and tests.
Most of this change is just moving files from `tools/render-test/*` to a new library project at `tools/slang-graphics/`. The most complicated code change there is renaming from `render_test` to `slang_graphics`.
The existing `hello` example was ported to use the graphics API layer instead of raw D3D11 API calls. It is still hard-coded to use the D3D11 back-end and the `SLANG_DXBC` target, so more work is needed if we want to actually support multiple APIs in the examples.
I also went ahead and implemented an extremely rudimentary set of APIs to abstract over the Windows platform calls that were being made in the example, so that we could potentially run that same example on other platforms. I did *not* port `render-test` to use those APIs, and I also did not implement them for anything but Windows (my assumption is that for most other platforms we would just use SDL2, and require people to ensure it is installed to their machine before building Slang examples).
Diffstat (limited to 'tools/render-test/render-gl.cpp')
| -rw-r--r-- | tools/render-test/render-gl.cpp | 1049 |
1 files changed, 0 insertions, 1049 deletions
diff --git a/tools/render-test/render-gl.cpp b/tools/render-test/render-gl.cpp deleted file mode 100644 index dc9f0c43a..000000000 --- a/tools/render-test/render-gl.cpp +++ /dev/null @@ -1,1049 +0,0 @@ -// render-gl.cpp -#include "render-gl.h" - -#include "options.h" -#include "render.h" - -#include <assert.h> -#include <stdio.h> -#include <stdlib.h> -#include "core/basic.h" -#include "core/secure-crt.h" -#include "external/stb/stb_image_write.h" - -#include "surface.h" - -// TODO(tfoley): eventually we should be able to run these -// tests on non-Windows targets to confirm that cross-compilation -// at least *works* on those platforms... -#define WIN32_LEAN_AND_MEAN -#define NOMINMAX -#include <Windows.h> -#undef WIN32_LEAN_AND_MEAN -#undef NOMINMAX - -#ifdef _MSC_VER -#include <stddef.h> -#if (_MSC_VER < 1900) -#define snprintf sprintf_s -#endif -#endif - -#pragma comment(lib, "opengl32") - -#include <GL/GL.h> -#include "external/glext.h" - -// We define an "X-macro" for mapping over loadable OpenGL -// extension entry point that we will use, so that we can -// easily write generic code to iterate over them. -#define MAP_GL_EXTENSION_FUNCS(F) \ - F(glCreateProgram, PFNGLCREATEPROGRAMPROC) \ - F(glCreateShader, PFNGLCREATESHADERPROC) \ - F(glShaderSource, PFNGLSHADERSOURCEPROC) \ - F(glCompileShader, PFNGLCOMPILESHADERPROC) \ - F(glGetShaderiv, PFNGLGETSHADERIVPROC) \ - F(glDeleteShader, PFNGLDELETESHADERPROC) \ - F(glAttachShader, PFNGLATTACHSHADERPROC) \ - F(glLinkProgram, PFNGLLINKPROGRAMPROC) \ - F(glGetProgramiv, PFNGLGETPROGRAMIVPROC) \ - F(glGetProgramInfoLog, PFNGLGETPROGRAMINFOLOGPROC) \ - F(glDeleteProgram, PFNGLDELETEPROGRAMPROC) \ - F(glGetShaderInfoLog, PFNGLGETSHADERINFOLOGPROC) \ - F(glGenBuffers, PFNGLGENBUFFERSPROC) \ - F(glBindBuffer, PFNGLBINDBUFFERPROC) \ - F(glBufferData, PFNGLBUFFERDATAPROC) \ - F(glDeleteBuffers, PFNGLDELETEBUFFERSPROC) \ - F(glMapBuffer, PFNGLMAPBUFFERPROC) \ - F(glUnmapBuffer, PFNGLUNMAPBUFFERPROC) \ - F(glUseProgram, PFNGLUSEPROGRAMPROC) \ - F(glBindBufferBase, PFNGLBINDBUFFERBASEPROC) \ - F(glVertexAttribPointer, PFNGLVERTEXATTRIBPOINTERPROC) \ - F(glEnableVertexAttribArray, PFNGLENABLEVERTEXATTRIBARRAYPROC) \ - F(glDisableVertexAttribArray, PFNGLDISABLEVERTEXATTRIBARRAYPROC) \ - F(glDebugMessageCallback, PFNGLDEBUGMESSAGECALLBACKPROC) \ - F(glDispatchCompute, PFNGLDISPATCHCOMPUTEPROC) \ - F(glActiveTexture, PFNGLACTIVETEXTUREPROC) \ - F(glCreateSamplers, PFNGLCREATESAMPLERSPROC) \ - F(glDeleteSamplers, PFNGLDELETESAMPLERSPROC) \ - F(glBindSampler, PFNGLBINDSAMPLERPROC) \ - F(glTexImage3D, PFNGLTEXIMAGE3DPROC) \ - F(glSamplerParameteri, PFNGLSAMPLERPARAMETERIPROC) \ - /* end */ - -using namespace Slang; - -namespace renderer_test { - -class GLRenderer : public Renderer -{ -public: - - // Renderer implementation - virtual SlangResult initialize(const Desc& desc, void* inWindowHandle) override; - virtual void setClearColor(const float color[4]) override; - virtual void clearFrame() override; - virtual void presentFrame() override; - virtual TextureResource* createTextureResource(Resource::Usage initialUsage, const TextureResource::Desc& desc, const TextureResource::Data* initData) override; - virtual BufferResource* createBufferResource(Resource::Usage initialUsage, const BufferResource::Desc& descIn, const void* initData) override; - virtual SlangResult captureScreenSurface(Surface& surfaceOut) override; - virtual InputLayout* createInputLayout(const InputElementDesc* inputElements, UInt inputElementCount) override; - virtual BindingState* createBindingState(const BindingState::Desc& bindingStateDesc) override; - virtual ShaderProgram* createProgram(const ShaderProgram::Desc& desc) override; - virtual void* map(BufferResource* buffer, MapFlavor flavor) override; - virtual void unmap(BufferResource* buffer) override; - virtual void setInputLayout(InputLayout* inputLayout) override; - virtual void setPrimitiveTopology(PrimitiveTopology topology) override; - virtual void setBindingState(BindingState* state); - virtual void setVertexBuffers(UInt startSlot, UInt slotCount, BufferResource*const* buffers, const UInt* strides, const UInt* offsets) override; - virtual void setShaderProgram(ShaderProgram* inProgram) override; - virtual void draw(UInt vertexCount, UInt startVertex) override; - virtual void dispatchCompute(int x, int y, int z) override; - virtual void submitGpuWork() override {} - virtual void waitForGpu() override {} - virtual RendererType getRendererType() const override { return RendererType::OpenGl; } - - protected: - enum - { - kMaxVertexStreams = 16, - }; - - struct VertexAttributeFormat - { - GLint componentCount; - GLenum componentType; - GLboolean normalized; - }; - - struct VertexAttributeDesc - { - VertexAttributeFormat format; - GLuint streamIndex; - GLsizei offset; - }; - - class InputLayoutImpl: public InputLayout - { - public: - VertexAttributeDesc m_attributes[kMaxVertexStreams]; - UInt m_attributeCount = 0; - }; - - class BufferResourceImpl: public BufferResource - { - public: - typedef BufferResource Parent; - - BufferResourceImpl(Usage initialUsage, const Desc& desc, GLRenderer* renderer, GLuint id, GLenum target): - Parent(desc), - m_renderer(renderer), - m_handle(id), - m_initialUsage(initialUsage), - m_target(target) - {} - ~BufferResourceImpl() - { - if (m_renderer) - { - m_renderer->glDeleteBuffers(1, &m_handle); - } - } - - Usage m_initialUsage; - GLRenderer* m_renderer; - GLuint m_handle; - GLenum m_target; - }; - - class TextureResourceImpl: public TextureResource - { - public: - typedef TextureResource Parent; - - TextureResourceImpl(Usage initialUsage, const Desc& desc, GLRenderer* renderer): - Parent(desc), - m_initialUsage(initialUsage), - m_renderer(renderer) - { - m_target = 0; - m_handle = 0; - } - - ~TextureResourceImpl() - { - if (m_handle) - { - glDeleteTextures(1, &m_handle); - } - } - - Usage m_initialUsage; - GLRenderer* m_renderer; - GLenum m_target; - GLuint m_handle; - }; - - struct BindingDetail - { - GLuint m_samplerHandle = 0; - }; - - class BindingStateImpl: public BindingState - { - public: - typedef BindingState Parent; - - /// Ctor - BindingStateImpl(const Desc& desc, GLRenderer* renderer): - Parent(desc), - m_renderer(renderer) - { - } - - ~BindingStateImpl() - { - if (m_renderer) - { - m_renderer->destroyBindingEntries(getDesc(), m_bindingDetails.Buffer()); - } - } - - GLRenderer* m_renderer; - List<BindingDetail> m_bindingDetails; - }; - - class ShaderProgramImpl : public ShaderProgram - { - public: - ShaderProgramImpl(GLRenderer* renderer, GLuint id): - m_renderer(renderer), - m_id(id) - { - } - ~ShaderProgramImpl() - { - if (m_renderer) - { - m_renderer->glDeleteProgram(m_id); - } - } - - GLuint m_id; - GLRenderer* m_renderer; - }; - - enum class GlPixelFormat - { - Unknown, - RGBA_Unorm_UInt8, - CountOf, - }; - - struct GlPixelFormatInfo - { - GLint internalFormat; // such as GL_RGBA8 - GLenum format; // such as GL_RGBA - GLenum formatType; // such as GL_UNSIGNED_BYTE - }; - - void destroyBindingEntries(const BindingState::Desc& desc, const BindingDetail* details); - - void bindBufferImpl(int target, UInt startSlot, UInt slotCount, BufferResource*const* buffers, const UInt* offsets); - void flushStateForDraw(); - GLuint loadShader(GLenum stage, char const* source); - void debugCallback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* message); - - /// Returns GlPixelFormat::Unknown if not an equivalent - static GlPixelFormat _getGlPixelFormat(Format format); - - static void APIENTRY staticDebugCallback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* message, const void* userParam); - static VertexAttributeFormat getVertexAttributeFormat(Format format); - - static void compileTimeAsserts(); - - HDC m_hdc; - HGLRC m_glContext; - float m_clearColor[4] = { 0, 0, 0, 0 }; - - RefPtr<ShaderProgramImpl> m_boundShaderProgram; - RefPtr<InputLayoutImpl> m_boundInputLayout; - - GLenum m_boundPrimitiveTopology = GL_TRIANGLES; - GLuint m_boundVertexStreamBuffers[kMaxVertexStreams]; - UInt m_boundVertexStreamStrides[kMaxVertexStreams]; - UInt m_boundVertexStreamOffsets[kMaxVertexStreams]; - - Desc m_desc; - - // 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) -#undef DECLARE_GL_EXTENSION_FUNC - - static const GlPixelFormatInfo s_pixelFormatInfos[]; /// Maps GlPixelFormat to a format info -}; - -/* static */GLRenderer::GlPixelFormat GLRenderer::_getGlPixelFormat(Format format) -{ - switch (format) - { - case Format::RGBA_Unorm_UInt8: return GlPixelFormat::RGBA_Unorm_UInt8; - default: return GlPixelFormat::Unknown; - } -} - -/* static */ const GLRenderer::GlPixelFormatInfo GLRenderer::s_pixelFormatInfos[] = -{ - // internalType, format, formatType - { 0, 0, 0}, // GlPixelFormat::Unknown - { GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE }, // GlPixelFormat::RGBA_Unorm_UInt8 -}; - -/* static */void GLRenderer::compileTimeAsserts() -{ - SLANG_COMPILE_TIME_ASSERT(SLANG_COUNT_OF(s_pixelFormatInfos) == int(GlPixelFormat::CountOf)); -} - -Renderer* createGLRenderer() -{ - return new GLRenderer(); -} - -void GLRenderer::debugCallback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* message) -{ - ::OutputDebugStringA("GL: "); - ::OutputDebugStringA(message); - ::OutputDebugStringA("\n"); - - switch (type) - { - case GL_DEBUG_TYPE_ERROR: - break; - default: - break; - } -} - -/* 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); -} - -/* static */GLRenderer::VertexAttributeFormat GLRenderer::getVertexAttributeFormat(Format format) -{ - switch (format) - { - default: assert(!"unexpected"); return VertexAttributeFormat(); - -#define CASE(NAME, COUNT, TYPE, NORMALIZED) \ - case Format::NAME: do { VertexAttributeFormat result = {COUNT, TYPE, NORMALIZED}; return result; } while (0) - - CASE(RGBA_Float32, 4, GL_FLOAT, GL_FALSE); - CASE(RGB_Float32, 3, GL_FLOAT, GL_FALSE); - CASE(RG_Float32, 2, GL_FLOAT, GL_FALSE); - CASE(R_Float32, 1, GL_FLOAT, GL_FALSE); -#undef CASE - } -} - -void GLRenderer::bindBufferImpl(int target, UInt startSlot, UInt slotCount, BufferResource*const* buffers, const UInt* offsets) -{ - for (UInt ii = 0; ii < slotCount; ++ii) - { - UInt slot = startSlot + ii; - - BufferResourceImpl* buffer = static_cast<BufferResourceImpl*>(buffers[ii]); - GLuint bufferID = buffer ? buffer->m_handle : 0; - - assert(!offsets || !offsets[ii]); - - glBindBufferBase(target, (GLuint)slot, bufferID); - } -} - -void GLRenderer::flushStateForDraw() -{ - auto layout = m_boundInputLayout.Ptr(); - auto attrCount = layout->m_attributeCount; - for (UInt ii = 0; ii < attrCount; ++ii) - { - auto& attr = layout->m_attributes[ii]; - - auto streamIndex = attr.streamIndex; - - glBindBuffer(GL_ARRAY_BUFFER, m_boundVertexStreamBuffers[streamIndex]); - - glVertexAttribPointer( - (GLuint)ii, - attr.format.componentCount, - attr.format.componentType, - attr.format.normalized, - (GLsizei)m_boundVertexStreamStrides[streamIndex], - (GLvoid*)(attr.offset + m_boundVertexStreamOffsets[streamIndex])); - - glEnableVertexAttribArray((GLuint)ii); - } - for (UInt ii = attrCount; ii < kMaxVertexStreams; ++ii) - { - glDisableVertexAttribArray((GLuint)ii); - } -} - -GLuint GLRenderer::loadShader(GLenum stage, const char* source) -{ - // GLSL is monumentally stupid. It officially requires the `#version` directive - // to be the first thing in the file, which wouldn't be so bad but the API - // doesn't provide a way to pass a `#define` into your shader other than by - // prepending it to the whole thing. - // - // We are going to solve this problem by doing some surgery on the source - // that was passed in. - - const char* sourceBegin = source; - const char* sourceEnd = source + strlen(source); - - // Look for a version directive in the user-provided source. - const char* versionBegin = strstr(source, "#version"); - const char* versionEnd = nullptr; - if (versionBegin) - { - // If we found a directive, then scan for the end-of-line - // after it, and use that to specify the slice. - versionEnd = strchr(versionBegin, '\n'); - if (!versionEnd) - { - versionEnd = sourceEnd; - } - else - { - versionEnd = versionEnd + 1; - } - } - else - { - // If we didn't find a directive, then treat it as being - // a zero-byte slice at the start of the string - versionBegin = sourceBegin; - versionEnd = sourceBegin; - } - - enum { kMaxSourceStringCount = 16 }; - const GLchar* sourceStrings[kMaxSourceStringCount]; - GLint sourceStringLengths[kMaxSourceStringCount]; - - int sourceStringCount = 0; - - const char* stagePrelude = "\n"; - switch (stage) - { -#define CASE(NAME) case GL_##NAME##_SHADER: stagePrelude = "#define __GLSL_" #NAME "__ 1\n"; break - - CASE(VERTEX); - CASE(TESS_CONTROL); - CASE(TESS_EVALUATION); - CASE(GEOMETRY); - CASE(FRAGMENT); - CASE(COMPUTE); - -#undef CASE - } - - const char* prelude = - "#define __GLSL__ 1\n" - ; - -#define ADD_SOURCE_STRING_SPAN(BEGIN, END) \ - sourceStrings[sourceStringCount] = BEGIN; \ - sourceStringLengths[sourceStringCount++] = GLint(END - BEGIN) \ - /* end */ - -#define ADD_SOURCE_STRING(BEGIN) \ - sourceStrings[sourceStringCount] = BEGIN; \ - sourceStringLengths[sourceStringCount++] = GLint(strlen(BEGIN)) \ - /* end */ - - ADD_SOURCE_STRING_SPAN(versionBegin, versionEnd); - ADD_SOURCE_STRING(stagePrelude); - ADD_SOURCE_STRING(prelude); - ADD_SOURCE_STRING_SPAN(sourceBegin, versionBegin); - ADD_SOURCE_STRING_SPAN(versionEnd, sourceEnd); - - auto shaderID = glCreateShader(stage); - glShaderSource( - shaderID, - sourceStringCount, - &sourceStrings[0], - &sourceStringLengths[0]); - glCompileShader(shaderID); - - GLint success = GL_FALSE; - glGetShaderiv(shaderID, GL_COMPILE_STATUS, &success); - if (!success) - { - int maxSize = 0; - glGetShaderiv(shaderID, GL_INFO_LOG_LENGTH, &maxSize); - - auto infoBuffer = (char*)malloc(maxSize); - - int infoSize = 0; - glGetShaderInfoLog(shaderID, maxSize, &infoSize, infoBuffer); - if (infoSize > 0) - { - fprintf(stderr, "%s", infoBuffer); - ::OutputDebugStringA(infoBuffer); - } - - glDeleteShader(shaderID); - return 0; - } - - return shaderID; -} - -void GLRenderer::destroyBindingEntries(const BindingState::Desc& desc, const BindingDetail* details) -{ - 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]; - - if (binding.bindingType == BindingType::Sampler && detail.m_samplerHandle != 0) - { - glDeleteSamplers(1, &detail.m_samplerHandle); - } - } -} - -// !!!!!!!!!!!!!!!!!!!!!!!!!!!! Renderer interface !!!!!!!!!!!!!!!!!!!!!!!!!! - -SlangResult GLRenderer::initialize(const Desc& desc, void* inWindowHandle) -{ - auto windowHandle = (HWND)inWindowHandle; - m_desc = desc; - - m_hdc = ::GetDC(windowHandle); - - 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(m_hdc, &pixelFormatDesc); - SetPixelFormat(m_hdc, pixelFormatIndex, &pixelFormatDesc); - - m_glContext = wglCreateContext(m_hdc); - wglMakeCurrent(m_hdc, m_glContext); - - auto renderer = glGetString(GL_RENDERER); - auto extensions = glGetString(GL_EXTENSIONS); - - // Load each of our extension functions by name - -#define LOAD_GL_EXTENSION_FUNC(NAME, TYPE) NAME = (TYPE) wglGetProcAddress(#NAME); - MAP_GL_EXTENSION_FUNCS(LOAD_GL_EXTENSION_FUNC) -#undef LOAD_GL_EXTENSION_FUNC - - glDisable(GL_DEPTH_TEST); - glDisable(GL_CULL_FACE); - - glViewport(0, 0, desc.width, desc.height); - - if (glDebugMessageCallback) - { - glEnable(GL_DEBUG_OUTPUT); - glDebugMessageCallback(staticDebugCallback, this); - } - - return SLANG_OK; -} - -void GLRenderer::setClearColor(const float color[4]) -{ - glClearColor(color[0], color[1], color[2], color[3]); -} - -void GLRenderer::clearFrame() -{ - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); -} - -void GLRenderer::presentFrame() -{ - glFlush(); - ::SwapBuffers(m_hdc); -} - -SlangResult GLRenderer::captureScreenSurface(Surface& surfaceOut) -{ - SLANG_RETURN_ON_FAIL(surfaceOut.allocate(m_desc.width, m_desc.height, Format::RGBA_Unorm_UInt8, 1, SurfaceAllocator::getMallocAllocator())); - glReadPixels(0, 0, m_desc.width, m_desc.height, GL_RGBA, GL_UNSIGNED_BYTE, surfaceOut.m_data); - surfaceOut.flipInplaceVertically(); - return SLANG_OK; -} - -TextureResource* GLRenderer::createTextureResource(Resource::Usage initialUsage, const TextureResource::Desc& descIn, const TextureResource::Data* initData) -{ - TextureResource::Desc srcDesc(descIn); - srcDesc.setDefaults(initialUsage); - - GlPixelFormat pixelFormat = _getGlPixelFormat(srcDesc.format); - if (pixelFormat == GlPixelFormat::Unknown) - { - return nullptr; - } - - const GlPixelFormatInfo& info = s_pixelFormatInfos[int(pixelFormat)]; - - const GLint internalFormat = info.internalFormat; - const GLenum format = info.format; - const GLenum formatType = info.formatType; - - RefPtr<TextureResourceImpl> texture(new TextureResourceImpl(initialUsage, srcDesc, this)); - - GLenum target = 0; - GLuint handle = 0; - glGenTextures(1, &handle); - - 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) - { - case Resource::Type::Texture1D: - { - if (srcDesc.arraySize > 0) - { - target = GL_TEXTURE_1D_ARRAY; - glBindTexture(target, handle); - - int slice = 0; - for (int i = 0; i < effectiveArraySize; i++) - { - for (int j = 0; j < srcDesc.numMipLevels; j++) - { - glTexImage2D(target, j, internalFormat, srcDesc.size.width, i, 0, format, formatType, data[slice++]); - } - } - } - else - { - target = GL_TEXTURE_1D; - glBindTexture(target, handle); - for (int i = 0; i < srcDesc.numMipLevels; i++) - { - glTexImage1D(target, i, internalFormat, srcDesc.size.width, 0, format, formatType, data[i]); - } - } - break; - } - case Resource::Type::TextureCube: - case Resource::Type::Texture2D: - { - if (srcDesc.arraySize > 0) - { - if (srcDesc.type == Resource::Type::TextureCube) - { - target = GL_TEXTURE_CUBE_MAP_ARRAY; - } - else - { - target = GL_TEXTURE_2D_ARRAY; - } - - glBindTexture(target, handle); - - int slice = 0; - for (int i = 0; i < effectiveArraySize; i++) - { - for (int j = 0; j < srcDesc.numMipLevels; j++) - { - glTexImage3D(target, j, internalFormat, srcDesc.size.width, srcDesc.size.height, slice, 0, format, formatType, data[slice++]); - } - } - } - else - { - if (srcDesc.type == Resource::Type::TextureCube) - { - target = GL_TEXTURE_CUBE_MAP; - glBindTexture(target, handle); - - int slice = 0; - for (int j = 0; j < 6; j++) - { - 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++]); - } - } - } - else - { - target = GL_TEXTURE_2D; - 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]); - } - } - } - break; - } - case Resource::Type::Texture3D: - { - target = GL_TEXTURE_3D; - 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]); - } - break; - } - default: return nullptr; - } - - glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_REPEAT); - glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_REPEAT); - glTexParameteri(target, GL_TEXTURE_WRAP_R, GL_REPEAT); - - // Assume regular sampling (might be superseded - if a combined sampler wanted) - glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); - glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameterf(target, GL_TEXTURE_MAX_ANISOTROPY_EXT, 8.0f); - - texture->m_target = target; - - return texture.detach(); -} - -static GLenum _calcUsage(Resource::Usage usage) -{ - typedef Resource::Usage Usage; - switch (usage) - { - case Usage::ConstantBuffer: return GL_DYNAMIC_DRAW; - default: return GL_STATIC_READ; - } -} - -static GLenum _calcTarget(Resource::Usage usage) -{ - typedef Resource::Usage Usage; - switch (usage) - { - case Usage::ConstantBuffer: return GL_UNIFORM_BUFFER; - default: return GL_SHADER_STORAGE_BUFFER; - } -} - -BufferResource* GLRenderer::createBufferResource(Resource::Usage initialUsage, const BufferResource::Desc& descIn, const void* initData) -{ - BufferResource::Desc desc(descIn); - desc.setDefaults(initialUsage); - - const GLenum target = _calcTarget(initialUsage); - // TODO: should derive from desc... - const GLenum usage = _calcUsage(initialUsage); - - GLuint bufferID = 0; - glGenBuffers(1, &bufferID); - glBindBuffer(target, bufferID); - - glBufferData(target, descIn.sizeInBytes, initData, usage); - - return new BufferResourceImpl(initialUsage, desc, this, bufferID, target); -} - -InputLayout* GLRenderer::createInputLayout(const InputElementDesc* inputElements, UInt inputElementCount) -{ - InputLayoutImpl* inputLayout = new InputLayoutImpl; - - inputLayout->m_attributeCount = inputElementCount; - for (UInt ii = 0; ii < inputElementCount; ++ii) - { - auto& inputAttr = inputElements[ii]; - auto& glAttr = inputLayout->m_attributes[ii]; - - glAttr.streamIndex = 0; - glAttr.format = getVertexAttributeFormat(inputAttr.format); - glAttr.offset = (GLsizei)inputAttr.offset; - } - - return (InputLayout*)inputLayout; -} - -void* GLRenderer::map(BufferResource* bufferIn, MapFlavor flavor) -{ - BufferResourceImpl* buffer = static_cast<BufferResourceImpl*>(bufferIn); - - //GLenum target = GL_UNIFORM_BUFFER; - - GLuint access = 0; - switch (flavor) - { - case MapFlavor::WriteDiscard: - case MapFlavor::HostWrite: - access = GL_WRITE_ONLY; - break; - case MapFlavor::HostRead: - access = GL_READ_ONLY; - break; - } - - glBindBuffer(buffer->m_target, buffer->m_handle); - - return glMapBuffer(buffer->m_target, access); -} - -void GLRenderer::unmap(BufferResource* bufferIn) -{ - BufferResourceImpl* buffer = static_cast<BufferResourceImpl*>(bufferIn); - glUnmapBuffer(buffer->m_target); -} - -void GLRenderer::setInputLayout(InputLayout* inputLayout) -{ - m_boundInputLayout = static_cast<InputLayoutImpl*>(inputLayout); -} - -void GLRenderer::setPrimitiveTopology(PrimitiveTopology topology) -{ - GLenum glTopology = 0; - switch (topology) - { -#define CASE(NAME, VALUE) case PrimitiveTopology::NAME: glTopology = VALUE; break - - CASE(TriangleList, GL_TRIANGLES); - -#undef CASE - } - m_boundPrimitiveTopology = glTopology; -} - -void GLRenderer::setVertexBuffers(UInt startSlot, UInt slotCount, BufferResource*const* buffers, const UInt* strides, const UInt* offsets) -{ - for (UInt ii = 0; ii < slotCount; ++ii) - { - UInt slot = startSlot + ii; - - BufferResourceImpl* buffer = static_cast<BufferResourceImpl*>(buffers[ii]); - GLuint bufferID = buffer ? buffer->m_handle : 0; - - m_boundVertexStreamBuffers[slot] = bufferID; - m_boundVertexStreamStrides[slot] = strides[ii]; - m_boundVertexStreamOffsets[slot] = offsets[ii]; - } -} - -void GLRenderer::setShaderProgram(ShaderProgram* programIn) -{ - ShaderProgramImpl* program = static_cast<ShaderProgramImpl*>(programIn); - m_boundShaderProgram = program; - GLuint programID = program ? program->m_id : 0; - glUseProgram(programID); -} - -void GLRenderer::draw(UInt vertexCount, UInt startVertex = 0) -{ - flushStateForDraw(); - - glDrawArrays(m_boundPrimitiveTopology, (GLint)startVertex, (GLsizei)vertexCount); -} - -void GLRenderer::dispatchCompute(int x, int y, int z) -{ - glDispatchCompute(x, y, z); -} - -BindingState* GLRenderer::createBindingState(const BindingState::Desc& bindingStateDesc) -{ - RefPtr<BindingStateImpl> bindingState(new BindingStateImpl(bindingStateDesc, this)); - - const auto& srcBindings = bindingStateDesc.m_bindings; - const int numBindings = int(srcBindings.Count()); - - auto& dstDetails = bindingState->m_bindingDetails; - dstDetails.SetSize(numBindings); - - for (int i = 0; i < numBindings; ++i) - { - auto& dstDetail = dstDetails[i]; - const auto& srcBinding = srcBindings[i]; - - - switch (srcBinding.bindingType) - { - case BindingType::Texture: - case BindingType::Buffer: - { - break; - } - case BindingType::CombinedTextureSampler: - { - assert(srcBinding.resource && srcBinding.resource->isTexture()); - TextureResourceImpl* texture = static_cast<TextureResourceImpl*>(srcBinding.resource.Ptr()); - const BindingState::SamplerDesc& samplerDesc = bindingStateDesc.m_samplerDescs[srcBinding.descIndex]; - - if (samplerDesc.isCompareSampler) - { - auto target = texture->m_target; - - glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(target, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE); - glTexParameteri(target, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL); - } - break; - } - case BindingType::Sampler: - { - const BindingState::SamplerDesc& samplerDesc = bindingStateDesc.m_samplerDescs[srcBinding.descIndex]; - - GLuint handle; - - glCreateSamplers(1, &handle); - glSamplerParameteri(handle, GL_TEXTURE_WRAP_S, GL_REPEAT); - glSamplerParameteri(handle, GL_TEXTURE_WRAP_T, GL_REPEAT); - glSamplerParameteri(handle, GL_TEXTURE_WRAP_R, GL_REPEAT); - - if (samplerDesc.isCompareSampler) - { - glSamplerParameteri(handle, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glSamplerParameteri(handle, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glSamplerParameteri(handle, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE); - glSamplerParameteri(handle, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL); - } - else - { - glSamplerParameteri(handle, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); - glSamplerParameteri(handle, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glSamplerParameteri(handle, GL_TEXTURE_MAX_ANISOTROPY_EXT, 8); - } - - dstDetail.m_samplerHandle = handle; - break; - } - } - } - - return bindingState.detach(); -} - -void GLRenderer::setBindingState(BindingState* stateIn) -{ - BindingStateImpl* state = static_cast<BindingStateImpl*>(stateIn); - - const auto& bindingDesc = state->getDesc(); - - const auto& details = state->m_bindingDetails; - const auto& bindings = bindingDesc.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]; - - switch (binding.bindingType) - { - case BindingType::Buffer: - { - const int bindingIndex = binding.registerRange.getSingleIndex(); - - BufferResourceImpl* buffer = static_cast<BufferResourceImpl*>(binding.resource.Ptr()); - glBindBufferBase(buffer->m_target, bindingIndex, buffer->m_handle); - break; - } - case BindingType::Sampler: - { - for (int index = binding.registerRange.index; index < binding.registerRange.index + binding.registerRange.size; ++index) - { - glBindSampler(index, detail.m_samplerHandle); - } - break; - } - case BindingType::Texture: - case BindingType::CombinedTextureSampler: - { - BufferResourceImpl* buffer = static_cast<BufferResourceImpl*>(binding.resource.Ptr()); - - const int bindingIndex = binding.registerRange.getSingleIndex(); - - glActiveTexture(GL_TEXTURE0 + bindingIndex); - glBindTexture(buffer->m_target, buffer->m_handle); - break; - } - } - } -} - -ShaderProgram* GLRenderer::createProgram(const ShaderProgram::Desc& desc) -{ - auto programID = glCreateProgram(); - if(desc.pipelineType == PipelineType::Compute ) - { - auto computeKernel = desc.findKernel(StageType::Compute); - auto computeShaderID = loadShader(GL_COMPUTE_SHADER, (char const*) computeKernel->codeBegin); - glAttachShader(programID, computeShaderID); - glLinkProgram(programID); - glDeleteShader(computeShaderID); - } - else - { - auto vertexKernel = desc.findKernel(StageType::Vertex); - auto fragmentKernel = desc.findKernel(StageType::Fragment); - - auto vertexShaderID = loadShader(GL_VERTEX_SHADER, (char const*) vertexKernel->codeBegin); - auto fragmentShaderID = loadShader(GL_FRAGMENT_SHADER, (char const*) fragmentKernel->codeBegin); - - glAttachShader(programID, vertexShaderID); - glAttachShader(programID, fragmentShaderID); - - - glLinkProgram(programID); - - glDeleteShader(vertexShaderID); - glDeleteShader(fragmentShaderID); - } - GLint success = GL_FALSE; - glGetProgramiv(programID, GL_LINK_STATUS, &success); - if (!success) - { - int maxSize = 0; - glGetProgramiv(programID, GL_INFO_LOG_LENGTH, &maxSize); - - auto infoBuffer = (char*)::malloc(maxSize); - - int infoSize = 0; - glGetProgramInfoLog(programID, maxSize, &infoSize, infoBuffer); - if (infoSize > 0) - { - fprintf(stderr, "%s", infoBuffer); - OutputDebugStringA(infoBuffer); - } - - ::free(infoBuffer); - - glDeleteProgram(programID); - return nullptr; - } - - return new ShaderProgramImpl(this, programID); -} - - -} // renderer_test |
