mirror of
https://github.com/overte-org/overte.git
synced 2025-04-23 10:13:22 +02:00
Merge pull request #13240 from jherico/feature/glsl_layouts
Update shader pipeline, improve mac startup time
This commit is contained in:
commit
7dd80d0180
354 changed files with 5887 additions and 5505 deletions
CMakeLists.txt
android
cmake
interface
libraries
display-plugins
CMakeLists.txt
src/display-plugins
entities-renderer
CMakeLists.txt
src
RenderableParticleEffectEntityItem.cppRenderablePolyLineEntityItem.cppRenderablePolyVoxEntityItem.cppRenderableShapeEntityItem.cpp
entities-renderer
paintStroke.slfpaintStroke.slvpaintStroke_fade.slfpaintStroke_fade.slvpolyvox.slfpolyvox.slvpolyvox_fade.slfpolyvox_fade.slvtextured_particle.slftextured_particle.slvgl/src/gl
gpu-gl-common/src/gpu/gl
GLBackend.cppGLBackend.hGLBackendPipeline.cppGLBackendShader.cppGLBackendTransform.cppGLPipeline.cppGLPipeline.hGLShader.cppGLShader.hGLTextureTransfer.cpp
gpu-gl/src/gpu
gl
gl41
gl45
gpu-gles/src/gpu
gpu
CMakeLists.txt
src/gpu
Batch.hContext.cppContext.hDrawColor.slfDrawColoredTexture.slfDrawNada.slfDrawTexcoordRectTransformUnitQuad.slvDrawTexture.slfDrawTextureMirroredX.slfDrawTextureOpaque.slfDrawTransformUnitQuad.slvDrawTransformVertexPosition.slvDrawUnitQuadTexcoord.slvDrawVertexPosition.slvDrawViewportQuadTransformTexcoord.slvDrawWhite.slfInputs.slhShader.cppShader.hShaderConstants.hStandardShaderLib.cppStandardShaderLib.hTextureTable.slhTransform.slh
null
graphics
CMakeLists.txt
src/graphics
procedural
|
@ -15,6 +15,7 @@ include("cmake/compiler.cmake")
|
|||
|
||||
if (BUILD_SCRIBE_ONLY)
|
||||
add_subdirectory(tools/scribe)
|
||||
add_subdirectory(tools/shader_reflect)
|
||||
return()
|
||||
endif()
|
||||
|
||||
|
|
|
@ -24,6 +24,7 @@ android {
|
|||
'-DANDROID_STL=c++_shared',
|
||||
'-DQT_CMAKE_PREFIX_PATH=' + HIFI_ANDROID_PRECOMPILED + '/qt/lib/cmake',
|
||||
'-DNATIVE_SCRIBE=' + HIFI_ANDROID_PRECOMPILED + '/scribe' + EXEC_SUFFIX,
|
||||
'-DNATIVE_SHREFLECT=' + HIFI_ANDROID_PRECOMPILED + '/shreflect' + EXEC_SUFFIX,
|
||||
'-DHIFI_ANDROID_PRECOMPILED=' + HIFI_ANDROID_PRECOMPILED,
|
||||
'-DRELEASE_NUMBER=' + RELEASE_NUMBER,
|
||||
'-DRELEASE_TYPE=' + RELEASE_TYPE,
|
||||
|
|
|
@ -164,18 +164,29 @@ def packages = [
|
|||
|
||||
|
||||
def scribeLocalFile='scribe' + EXEC_SUFFIX
|
||||
|
||||
def scribeFile='scribe_linux_x86_64'
|
||||
def scribeChecksum='ca4b904f52f4f993c29175ba96798fa6'
|
||||
def scribeVersion='u_iTrJDaE95i2abTPXOpPZckGBIim53G'
|
||||
|
||||
def shreflectLocalFile='shreflect' + EXEC_SUFFIX
|
||||
def shreflectFile='shreflect_linux_x86_64'
|
||||
def shreflectChecksum='d6094a8580066c0b6f4e80b5adfb1d98'
|
||||
def shreflectVersion='jnrpudh6fptIg6T2.Z6fgKP2ultAdKmE'
|
||||
|
||||
if (Os.isFamily(Os.FAMILY_MAC)) {
|
||||
scribeFile = 'scribe_osx_x86_64'
|
||||
scribeChecksum='72db9d32d4e1e50add755570ac5eb749'
|
||||
scribeVersion='DAW0DmnjCRib4MD8x93bgc2Z2MpPojZC'
|
||||
shreflectFile='shreflect_osx_x86_64'
|
||||
shreflectChecksum='d613ef0703c21371fee93fd2e54b964f'
|
||||
shreflectVersion='.rYNzjSFq6WtWDnE5KIKRIAGyJtr__ad'
|
||||
} else if (Os.isFamily(Os.FAMILY_WINDOWS)) {
|
||||
scribeFile = 'scribe_win32_x86_64.exe'
|
||||
scribeChecksum='678e43d290c90fda670c6fefe038a06d'
|
||||
scribeVersion='PuullrA_bPlO9kXZRt8rLe536X1UI.m7'
|
||||
shreflectFile='shreflect_win32_x86_64.exe'
|
||||
shreflectChecksum='6f4a77b8cceb3f1bbc655132c3665060'
|
||||
shreflectVersion='iIyCyza1nelkbI7ihybF59bBlwrfAC3D'
|
||||
}
|
||||
|
||||
def options = [
|
||||
|
@ -450,11 +461,27 @@ task fixScribePermissions(type: Exec, dependsOn: verifyScribe) {
|
|||
commandLine 'chmod', 'a+x', HIFI_ANDROID_PRECOMPILED + '/' + scribeLocalFile
|
||||
}
|
||||
|
||||
task setupScribe(dependsOn: verifyScribe) { }
|
||||
task downloadShreflect(type: Download) {
|
||||
src baseUrl + shreflectFile + '?versionId=' + shreflectVersion
|
||||
dest new File(baseFolder, shreflectLocalFile)
|
||||
onlyIfNewer true
|
||||
}
|
||||
|
||||
task verifyShreflect(type: Verify, dependsOn: downloadShreflect) {
|
||||
src new File(baseFolder, shreflectLocalFile);
|
||||
checksum shreflectChecksum
|
||||
}
|
||||
|
||||
task fixShreflectPermissions(type: Exec, dependsOn: verifyShreflect) {
|
||||
commandLine 'chmod', 'a+x', HIFI_ANDROID_PRECOMPILED + '/' + shreflectLocalFile
|
||||
}
|
||||
|
||||
task setupScribe(dependsOn: [verifyScribe, verifyShreflect]) { }
|
||||
|
||||
// On Windows, we don't need to set the executable bit, but on OSX and Unix we do
|
||||
if (!Os.isFamily(Os.FAMILY_WINDOWS)) {
|
||||
setupScribe.dependsOn fixScribePermissions
|
||||
setupScribe.dependsOn fixShreflectPermissions
|
||||
}
|
||||
|
||||
task extractGvrBinaries(dependsOn: extractDependencies) {
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DDEBUG")
|
||||
set(CMAKE_CXX_STANDARD 14)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
if (NOT "${CMAKE_SIZEOF_VOID_P}" EQUAL "8")
|
||||
message( FATAL_ERROR "Only 64 bit builds supported." )
|
||||
endif()
|
||||
|
||||
if (WIN32)
|
||||
if (NOT "${CMAKE_SIZEOF_VOID_P}" EQUAL "8")
|
||||
message( FATAL_ERROR "Only 64 bit builds supported." )
|
||||
endif()
|
||||
|
||||
add_definitions(-DNOMINMAX -D_CRT_SECURE_NO_WARNINGS)
|
||||
|
||||
if (NOT WINDOW_SDK_PATH)
|
||||
|
@ -52,32 +54,27 @@ endif()
|
|||
|
||||
if (ANDROID)
|
||||
# assume that the toolchain selected for android has C++11 support
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14")
|
||||
elseif(APPLE)
|
||||
set(CMAKE_XCODE_ATTRIBUTE_CLANG_CXX_LANGUAGE_STANDARD "c++14")
|
||||
set(CMAKE_XCODE_ATTRIBUTE_CLANG_CXX_LIBRARY "libc++")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --stdlib=libc++")
|
||||
if (CMAKE_GENERATOR STREQUAL "Xcode")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g")
|
||||
set(CMAKE_XCODE_ATTRIBUTE_GCC_GENERATE_DEBUGGING_SYMBOLS[variant=Release] "YES")
|
||||
set(CMAKE_XCODE_ATTRIBUTE_DEBUG_INFORMATION_FORMAT[variant=Release] "dwarf-with-dsym")
|
||||
set(CMAKE_XCODE_ATTRIBUTE_DEPLOYMENT_POSTPROCESSING[variant=Release] "YES")
|
||||
endif()
|
||||
elseif ((NOT MSVC12) AND (NOT MSVC14))
|
||||
include(CheckCXXCompilerFlag)
|
||||
CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11)
|
||||
CHECK_CXX_COMPILER_FLAG("-std=c++0x" COMPILER_SUPPORTS_CXX0X)
|
||||
if (COMPILER_SUPPORTS_CXX11)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
|
||||
elseif(COMPILER_SUPPORTS_CXX0X)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")
|
||||
CHECK_CXX_COMPILER_FLAG("-std=c++14" COMPILER_SUPPORTS_CXX14)
|
||||
if (COMPILER_SUPPORTS_CXX14)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14")
|
||||
else()
|
||||
message(FATAL_ERROR "The compiler ${CMAKE_CXX_COMPILER} has no C++11 support. Please use a different C++ compiler.")
|
||||
endif()
|
||||
endif ()
|
||||
|
||||
if (CMAKE_GENERATOR STREQUAL "Xcode")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g")
|
||||
set(CMAKE_XCODE_ATTRIBUTE_GCC_GENERATE_DEBUGGING_SYMBOLS[variant=Release] "YES")
|
||||
set(CMAKE_XCODE_ATTRIBUTE_DEBUG_INFORMATION_FORMAT[variant=Release] "dwarf-with-dsym")
|
||||
set(CMAKE_XCODE_ATTRIBUTE_DEPLOYMENT_POSTPROCESSING[variant=Release] "YES")
|
||||
endif()
|
||||
|
||||
if (APPLE)
|
||||
set(CMAKE_XCODE_ATTRIBUTE_CLANG_CXX_LANGUAGE_STANDARD "c++11")
|
||||
set(CMAKE_XCODE_ATTRIBUTE_CLANG_CXX_LIBRARY "libc++")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --stdlib=libc++")
|
||||
endif ()
|
||||
|
||||
if (NOT ANDROID_LIB_DIR)
|
||||
set(ANDROID_LIB_DIR $ENV{ANDROID_LIB_DIR})
|
||||
|
@ -110,4 +107,4 @@ if (APPLE)
|
|||
# set that as the SDK to use
|
||||
set(CMAKE_OSX_SYSROOT ${_OSX_DESIRED_SDK_PATH}/MacOSX${OSX_SDK}.sdk)
|
||||
endif ()
|
||||
endif ()
|
||||
endif ()
|
||||
|
|
22
cmake/externals/json/CMakeLists.txt
vendored
Normal file
22
cmake/externals/json/CMakeLists.txt
vendored
Normal file
|
@ -0,0 +1,22 @@
|
|||
set(EXTERNAL_NAME json)
|
||||
|
||||
include(ExternalProject)
|
||||
ExternalProject_Add(
|
||||
${EXTERNAL_NAME}
|
||||
URL https://hifi-public.s3.amazonaws.com/dependencies/json_3.1.2.zip
|
||||
URL_MD5 94dbf6ea25a7569ddc0ab6e20862cf16
|
||||
BINARY_DIR ${EXTERNAL_PROJECT_PREFIX}/build
|
||||
CMAKE_ARGS -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR> ${EXTERNAL_ARGS}
|
||||
CONFIGURE_COMMAND ""
|
||||
BUILD_COMMAND ""
|
||||
INSTALL_COMMAND ""
|
||||
LOG_DOWNLOAD 1
|
||||
)
|
||||
|
||||
# Hide this external target (for ide users)
|
||||
set_target_properties(${EXTERNAL_NAME} PROPERTIES FOLDER "hidden/externals")
|
||||
|
||||
ExternalProject_Get_Property(${EXTERNAL_NAME} SOURCE_DIR)
|
||||
|
||||
string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER)
|
||||
set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${SOURCE_DIR} CACHE PATH "List of json include directories")
|
|
@ -8,6 +8,12 @@
|
|||
# See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
#
|
||||
|
||||
function(global_append varName varValue)
|
||||
get_property(LOCAL_LIST GLOBAL PROPERTY ${varName})
|
||||
list(APPEND LOCAL_LIST ${varValue})
|
||||
set_property(GLOBAL PROPERTY ${varName} ${LOCAL_LIST})
|
||||
endfunction()
|
||||
|
||||
function(AUTOSCRIBE_SHADER SHADER_FILE)
|
||||
# Grab include files
|
||||
foreach(includeFile ${ARGN})
|
||||
|
@ -45,11 +51,8 @@ function(AUTOSCRIBE_SHADER SHADER_FILE)
|
|||
elseif(${SHADER_EXT} STREQUAL .slg)
|
||||
set(SHADER_TYPE geom)
|
||||
endif()
|
||||
set(SHADER_TARGET ${SHADER_TARGET}_${SHADER_TYPE})
|
||||
|
||||
set(SHADER_TARGET "${SHADERS_DIR}/${SHADER_TARGET}")
|
||||
set(SHADER_TARGET_HEADER ${SHADER_TARGET}.h)
|
||||
set(SHADER_TARGET_SOURCE ${SHADER_TARGET}.cpp)
|
||||
file(MAKE_DIRECTORY "${SHADERS_DIR}/${SHADER_LIB}")
|
||||
set(SHADER_TARGET "${SHADERS_DIR}/${SHADER_LIB}/${SHADER_TARGET}.${SHADER_TYPE}")
|
||||
set(SCRIBE_COMMAND scribe)
|
||||
|
||||
# Target dependant Custom rule on the SHADER_FILE
|
||||
|
@ -63,65 +66,232 @@ function(AUTOSCRIBE_SHADER SHADER_FILE)
|
|||
else ()
|
||||
set(GLPROFILE PC_GL)
|
||||
endif()
|
||||
set(SCRIBE_ARGS -c++ -T ${SHADER_TYPE} -D GLPROFILE ${GLPROFILE} ${SCRIBE_INCLUDES} -o ${SHADER_TARGET} ${SHADER_FILE})
|
||||
set(SCRIBE_ARGS -T ${SHADER_TYPE} -D GLPROFILE ${GLPROFILE} ${SCRIBE_INCLUDES} -o ${SHADER_TARGET} ${SHADER_FILE})
|
||||
add_custom_command(
|
||||
OUTPUT ${SHADER_TARGET_HEADER} ${SHADER_TARGET_SOURCE}
|
||||
OUTPUT ${SHADER_TARGET}
|
||||
COMMAND ${SCRIBE_COMMAND} ${SCRIBE_ARGS}
|
||||
DEPENDS ${SCRIBE_COMMAND} ${SHADER_INCLUDE_FILES} ${SHADER_FILE}
|
||||
DEPENDS ${SHADER_FILE} ${SCRIBE_COMMAND} ${SHADER_INCLUDE_FILES}
|
||||
)
|
||||
|
||||
#output the generated file name
|
||||
set(AUTOSCRIBE_SHADER_RETURN ${SHADER_TARGET_HEADER} ${SHADER_TARGET_SOURCE} PARENT_SCOPE)
|
||||
|
||||
file(GLOB INCLUDE_FILES ${SHADER_TARGET_HEADER})
|
||||
|
||||
set(AUTOSCRIBE_SHADER_RETURN ${SHADER_TARGET} PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
macro(AUTOSCRIBE_APPEND_SHADER_SOURCES)
|
||||
if (NOT("${ARGN}" STREQUAL ""))
|
||||
set_property(GLOBAL PROPERTY ${TARGET_NAME}_SHADER_SOURCES "${ARGN}")
|
||||
global_append(GLOBAL_SHADER_LIBS ${TARGET_NAME})
|
||||
global_append(GLOBAL_SHADER_SOURCES "${ARGN}")
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
macro(AUTOSCRIBE_SHADER_LIB)
|
||||
set(HIFI_LIBRARIES_SHADER_INCLUDE_FILES "")
|
||||
unset(HIFI_LIBRARIES_SHADER_INCLUDE_FILES)
|
||||
set(SRC_FOLDER "${CMAKE_SOURCE_DIR}/libraries/${TARGET_NAME}/src")
|
||||
|
||||
file(GLOB_RECURSE SHADER_INCLUDE_FILES ${SRC_FOLDER}/*.slh)
|
||||
file(GLOB_RECURSE SHADER_VERTEX_FILES ${SRC_FOLDER}/*.slv)
|
||||
file(GLOB_RECURSE SHADER_FRAGMENT_FILES ${SRC_FOLDER}/*.slf)
|
||||
file(GLOB_RECURSE SHADER_GEOMETRY_FILES ${SRC_FOLDER}/*.slg)
|
||||
file(GLOB_RECURSE SHADER_COMPUTE_FILES ${SRC_FOLDER}/*.slc)
|
||||
|
||||
unset(SHADER_SOURCE_FILES)
|
||||
list(APPEND SHADER_SOURCE_FILES ${SHADER_VERTEX_FILES})
|
||||
list(APPEND SHADER_SOURCE_FILES ${SHADER_FRAGMENT_FILES})
|
||||
list(APPEND SHADER_SOURCE_FILES ${SHADER_GEOMETRY_FILES})
|
||||
list(APPEND SHADER_SOURCE_FILES ${SHADER_COMPUTE_FILES})
|
||||
|
||||
unset(LOCAL_SHADER_SOURCES)
|
||||
list(APPEND LOCAL_SHADER_SOURCES ${SHADER_SOURCE_FILES})
|
||||
list(APPEND LOCAL_SHADER_SOURCES ${SHADER_INCLUDE_FILES})
|
||||
|
||||
AUTOSCRIBE_APPEND_SHADER_SOURCES(${LOCAL_SHADER_SOURCES})
|
||||
|
||||
file(RELATIVE_PATH RELATIVE_LIBRARY_DIR_PATH ${CMAKE_CURRENT_SOURCE_DIR} "${HIFI_LIBRARY_DIR}")
|
||||
foreach(HIFI_LIBRARY ${ARGN})
|
||||
#if (NOT TARGET ${HIFI_LIBRARY})
|
||||
# file(GLOB_RECURSE HIFI_LIBRARIES_SHADER_INCLUDE_FILES ${RELATIVE_LIBRARY_DIR_PATH}/${HIFI_LIBRARY}/src/)
|
||||
#endif ()
|
||||
|
||||
#file(GLOB_RECURSE HIFI_LIBRARIES_SHADER_INCLUDE_FILES ${HIFI_LIBRARY_DIR}/${HIFI_LIBRARY}/src/*.slh)
|
||||
list(APPEND HIFI_LIBRARIES_SHADER_INCLUDE_FILES ${HIFI_LIBRARY_DIR}/${HIFI_LIBRARY}/src)
|
||||
endforeach()
|
||||
#message("${TARGET_NAME} ${HIFI_LIBRARIES_SHADER_INCLUDE_FILES}")
|
||||
endmacro()
|
||||
|
||||
file(GLOB_RECURSE SHADER_INCLUDE_FILES src/*.slh)
|
||||
file(GLOB_RECURSE SHADER_SOURCE_FILES src/*.slv src/*.slf src/*.slg)
|
||||
macro(AUTOSCRIBE_PROGRAM)
|
||||
set(oneValueArgs NAME VERTEX FRAGMENT GEOMETRY COMPUTE)
|
||||
cmake_parse_arguments(AUTOSCRIBE_PROGRAM "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
|
||||
if (NOT (DEFINED AUTOSCRIBE_PROGRAM_NAME))
|
||||
message(FATAL_ERROR "Programs must have a name and both a vertex and fragment shader")
|
||||
endif()
|
||||
if (NOT (DEFINED AUTOSCRIBE_PROGRAM_VERTEX))
|
||||
set(AUTOSCRIBE_PROGRAM_VERTEX ${AUTOSCRIBE_PROGRAM_NAME})
|
||||
endif()
|
||||
if (NOT (DEFINED AUTOSCRIBE_PROGRAM_FRAGMENT))
|
||||
set(AUTOSCRIBE_PROGRAM_FRAGMENT ${AUTOSCRIBE_PROGRAM_NAME})
|
||||
endif()
|
||||
|
||||
#make the shader folder
|
||||
set(SHADERS_DIR "${CMAKE_CURRENT_BINARY_DIR}/shaders/${TARGET_NAME}")
|
||||
file(MAKE_DIRECTORY ${SHADERS_DIR})
|
||||
if (NOT (${AUTOSCRIBE_PROGRAM_VERTEX} MATCHES ".*::.*"))
|
||||
set(AUTOSCRIBE_PROGRAM_VERTEX "vertex::${AUTOSCRIBE_PROGRAM_VERTEX}")
|
||||
endif()
|
||||
if (NOT (${AUTOSCRIBE_PROGRAM_FRAGMENT} MATCHES ".*::.*"))
|
||||
set(AUTOSCRIBE_PROGRAM_FRAGMENT "fragment::${AUTOSCRIBE_PROGRAM_FRAGMENT}")
|
||||
endif()
|
||||
|
||||
#message("${TARGET_NAME} ${SHADER_INCLUDE_FILES}")
|
||||
set(AUTOSCRIBE_SHADER_SRC "")
|
||||
foreach(SHADER_FILE ${SHADER_SOURCE_FILES})
|
||||
AUTOSCRIBE_SHADER(${SHADER_FILE} ${SHADER_INCLUDE_FILES})
|
||||
unset(AUTOSCRIBE_PROGRAM_MAP)
|
||||
list(APPEND AUTOSCRIBE_PROGRAM_MAP AUTOSCRIBE_PROGRAM_VERTEX)
|
||||
list(APPEND AUTOSCRIBE_PROGRAM_MAP ${AUTOSCRIBE_PROGRAM_VERTEX})
|
||||
list(APPEND AUTOSCRIBE_PROGRAM_MAP AUTOSCRIBE_PROGRAM_FRAGMENT)
|
||||
list(APPEND AUTOSCRIBE_PROGRAM_MAP ${AUTOSCRIBE_PROGRAM_FRAGMENT})
|
||||
global_append(${TARGET_NAME}_PROGRAMS ${AUTOSCRIBE_PROGRAM_NAME})
|
||||
set_property(GLOBAL PROPERTY ${AUTOSCRIBE_PROGRAM_NAME} "${AUTOSCRIBE_PROGRAM_MAP}")
|
||||
endmacro()
|
||||
|
||||
macro(unpack_map)
|
||||
set(MAP_VAR "${ARGN}")
|
||||
list(LENGTH MAP_VAR MAP_SIZE)
|
||||
MATH(EXPR MAP_ENTRY_RANGE "(${MAP_SIZE} / 2) - 1")
|
||||
foreach(INDEX RANGE ${MAP_ENTRY_RANGE})
|
||||
MATH(EXPR INDEX_NAME "${INDEX} * 2")
|
||||
MATH(EXPR INDEX_VAL "${INDEX_NAME} + 1")
|
||||
list(GET MAP_VAR ${INDEX_NAME} VAR_NAME)
|
||||
list(GET MAP_VAR ${INDEX_VAL} VAR_VAL)
|
||||
set(${VAR_NAME} ${VAR_VAL})
|
||||
endforeach()
|
||||
endmacro()
|
||||
|
||||
macro(PROCESS_SHADER_FILE)
|
||||
AUTOSCRIBE_SHADER(${SHADER} ${ALL_SHADER_HEADERS} ${HIFI_LIBRARIES_SHADER_INCLUDE_FILES})
|
||||
file(TO_CMAKE_PATH "${AUTOSCRIBE_SHADER_RETURN}" AUTOSCRIBE_GENERATED_FILE)
|
||||
set_property(SOURCE ${AUTOSCRIBE_GENERATED_FILE} PROPERTY SKIP_AUTOMOC ON)
|
||||
list(APPEND AUTOSCRIBE_SHADER_SRC ${AUTOSCRIBE_GENERATED_FILE})
|
||||
endforeach()
|
||||
#message(${TARGET_NAME} ${AUTOSCRIBE_SHADER_SRC})
|
||||
|
||||
if (WIN32)
|
||||
source_group("Shaders" FILES ${SHADER_INCLUDE_FILES})
|
||||
source_group("Shaders" FILES ${SHADER_SOURCE_FILES})
|
||||
source_group("Shaders\\generated" FILES ${AUTOSCRIBE_SHADER_SRC})
|
||||
endif()
|
||||
|
||||
list(APPEND AUTOSCRIBE_SHADER_LIB_SRC ${SHADER_INCLUDE_FILES})
|
||||
list(APPEND AUTOSCRIBE_SHADER_LIB_SRC ${SHADER_SOURCE_FILES})
|
||||
list(APPEND AUTOSCRIBE_SHADER_LIB_SRC ${AUTOSCRIBE_SHADER_SRC})
|
||||
|
||||
# Link library shaders, if they exist
|
||||
include_directories("${SHADERS_DIR}")
|
||||
|
||||
# Add search directory to find gpu/Shader.h
|
||||
include_directories("${HIFI_LIBRARY_DIR}/gpu/src")
|
||||
|
||||
source_group("Compiled/${SHADER_LIB}" FILES ${AUTOSCRIBE_GENERATED_FILE})
|
||||
set(REFLECTED_SHADER "${AUTOSCRIBE_GENERATED_FILE}.json")
|
||||
source_group("Reflected/${SHADER_LIB}" FILES ${REFLECTED_SHADER})
|
||||
list(APPEND COMPILED_SHADERS ${AUTOSCRIBE_GENERATED_FILE})
|
||||
get_filename_component(ENUM_NAME ${SHADER} NAME_WE)
|
||||
string(CONCAT SHADER_ENUMS "${SHADER_ENUMS}" "${ENUM_NAME} = ${SHADER_COUNT},\n")
|
||||
MATH(EXPR SHADER_COUNT "${SHADER_COUNT}+1")
|
||||
endmacro()
|
||||
|
||||
macro(AUTOSCRIBE_SHADER_FINISH)
|
||||
get_property(GLOBAL_SHADER_LIBS GLOBAL PROPERTY GLOBAL_SHADER_LIBS)
|
||||
list(REMOVE_DUPLICATES GLOBAL_SHADER_LIBS)
|
||||
set(SHADER_COUNT 0)
|
||||
set(PROGRAM_COUNT 0)
|
||||
set(SHADERS_DIR "${CMAKE_CURRENT_BINARY_DIR}/shaders")
|
||||
set(SHADER_ENUMS "")
|
||||
file(MAKE_DIRECTORY ${SHADERS_DIR})
|
||||
|
||||
unset(COMPILED_SHADERS)
|
||||
foreach(SHADER_LIB ${GLOBAL_SHADER_LIBS})
|
||||
get_property(LIB_SHADER_SOURCES GLOBAL PROPERTY ${SHADER_LIB}_SHADER_SOURCES)
|
||||
get_property(LIB_PROGRAMS GLOBAL PROPERTY ${SHADER_LIB}_PROGRAMS)
|
||||
list(REMOVE_DUPLICATES LIB_SHADER_SOURCES)
|
||||
string(REGEX REPLACE "[-]" "_" SHADER_NAMESPACE ${SHADER_LIB})
|
||||
list(APPEND HIFI_LIBRARIES_SHADER_INCLUDE_FILES "${CMAKE_SOURCE_DIR}/libraries/${SHADER_LIB}/src")
|
||||
|
||||
unset(VERTEX_SHADERS)
|
||||
unset(FRAGMENT_SHADERS)
|
||||
unset(SHADER_HEADERS)
|
||||
|
||||
foreach(SHADER_FILE ${LIB_SHADER_SOURCES})
|
||||
if (SHADER_FILE MATCHES ".*\\.slv")
|
||||
list(APPEND VERTEX_SHADERS ${SHADER_FILE})
|
||||
elseif (SHADER_FILE MATCHES ".*\\.slf")
|
||||
list(APPEND FRAGMENT_SHADERS ${SHADER_FILE})
|
||||
elseif (SHADER_FILE MATCHES ".*\\.slh")
|
||||
list(APPEND SHADER_HEADERS ${SHADER_FILE})
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
if (DEFINED SHADER_HEADERS)
|
||||
list(REMOVE_DUPLICATES SHADER_HEADERS)
|
||||
source_group("${SHADER_LIB}/Headers" FILES ${SHADER_HEADERS})
|
||||
list(APPEND ALL_SHADER_HEADERS ${SHADER_HEADERS})
|
||||
list(APPEND ALL_SCRIBE_SHADERS ${SHADER_HEADERS})
|
||||
endif()
|
||||
|
||||
string(CONCAT SHADER_ENUMS "${SHADER_ENUMS}" "namespace ${SHADER_NAMESPACE} {\n")
|
||||
if (DEFINED VERTEX_SHADERS)
|
||||
list(REMOVE_DUPLICATES VERTEX_SHADERS)
|
||||
source_group("${SHADER_LIB}/Vertex" FILES ${VERTEX_SHADERS})
|
||||
list(APPEND ALL_SCRIBE_SHADERS ${VERTEX_SHADERS})
|
||||
string(CONCAT SHADER_ENUMS "${SHADER_ENUMS}" "namespace vertex { enum {\n")
|
||||
foreach(SHADER ${VERTEX_SHADERS})
|
||||
process_shader_file()
|
||||
endforeach()
|
||||
string(CONCAT SHADER_ENUMS "${SHADER_ENUMS}" "}; } // vertex \n")
|
||||
endif()
|
||||
|
||||
if (DEFINED FRAGMENT_SHADERS)
|
||||
list(REMOVE_DUPLICATES FRAGMENT_SHADERS)
|
||||
source_group("${SHADER_LIB}/Fragment" FILES ${FRAGMENT_SHADERS})
|
||||
list(APPEND ALL_SCRIBE_SHADERS ${FRAGMENT_SHADERS})
|
||||
string(CONCAT SHADER_ENUMS "${SHADER_ENUMS}" "namespace fragment { enum {\n")
|
||||
foreach(SHADER ${FRAGMENT_SHADERS})
|
||||
process_shader_file()
|
||||
endforeach()
|
||||
string(CONCAT SHADER_ENUMS "${SHADER_ENUMS}" "}; } // fragment \n")
|
||||
endif()
|
||||
|
||||
if (DEFINED LIB_PROGRAMS)
|
||||
string(CONCAT SHADER_ENUMS "${SHADER_ENUMS}" "namespace program { enum {\n")
|
||||
foreach(LIB_PROGRAM ${LIB_PROGRAMS})
|
||||
get_property(LIB_PROGRAM_MAP GLOBAL PROPERTY ${LIB_PROGRAM})
|
||||
unpack_map(${LIB_PROGRAM_MAP})
|
||||
string(CONCAT SHADER_ENUMS "${SHADER_ENUMS}" "${LIB_PROGRAM} = (${AUTOSCRIBE_PROGRAM_VERTEX} << 16) | ${AUTOSCRIBE_PROGRAM_FRAGMENT},\n")
|
||||
MATH(EXPR PROGRAM_COUNT "${PROGRAM_COUNT}+1")
|
||||
list(APPEND SHADER_ALL_PROGRAMS "${SHADER_NAMESPACE}::program::${LIB_PROGRAM}")
|
||||
endforeach()
|
||||
string(CONCAT SHADER_ENUMS "${SHADER_ENUMS}" "}; } // program \n")
|
||||
endif()
|
||||
string(CONCAT SHADER_ENUMS "${SHADER_ENUMS}" "} // namespace ${SHADER_NAMESPACE}\n")
|
||||
endforeach()
|
||||
|
||||
set(SHADER_PROGRAMS_ARRAY "")
|
||||
foreach(SHADER_PROGRAM ${SHADER_ALL_PROGRAMS})
|
||||
string(CONCAT SHADER_PROGRAMS_ARRAY "${SHADER_PROGRAMS_ARRAY}" " ${SHADER_PROGRAM},\n")
|
||||
endforeach()
|
||||
|
||||
set(SHREFLECT_COMMAND shreflect)
|
||||
set(SHREFLECT_DEPENDENCY shreflect)
|
||||
if (ANDROID)
|
||||
set(SHREFLECT_COMMAND ${NATIVE_SHREFLECT})
|
||||
unset(SHREFLECT_DEPENDENCY)
|
||||
endif()
|
||||
|
||||
set(SHADER_COUNT 0)
|
||||
foreach(COMPILED_SHADER ${COMPILED_SHADERS})
|
||||
set(REFLECTED_SHADER "${COMPILED_SHADER}.json")
|
||||
list(APPEND COMPILED_SHADER_REFLECTIONS ${REFLECTED_SHADER})
|
||||
string(CONCAT SHADER_QRC "${SHADER_QRC}" "<file alias=\"${SHADER_COUNT}\">${COMPILED_SHADER}</file>\n")
|
||||
string(CONCAT SHADER_QRC "${SHADER_QRC}" "<file alias=\"${SHADER_COUNT}_reflection\">${REFLECTED_SHADER}</file>\n")
|
||||
MATH(EXPR SHADER_COUNT "${SHADER_COUNT}+1")
|
||||
add_custom_command(
|
||||
OUTPUT ${REFLECTED_SHADER}
|
||||
COMMAND ${SHREFLECT_COMMAND} ${COMPILED_SHADER}
|
||||
DEPENDS ${SHREFLECT_DEPENDENCY} ${COMPILED_SHADER}
|
||||
)
|
||||
endforeach()
|
||||
|
||||
# Custom targets required to force generation of the shaders via scribe
|
||||
add_custom_target(scribe_shaders SOURCES ${ALL_SCRIBE_SHADERS})
|
||||
add_custom_target(compiled_shaders SOURCES ${COMPILED_SHADERS})
|
||||
add_custom_target(reflected_shaders SOURCES ${COMPILED_SHADER_REFLECTIONS})
|
||||
set_target_properties(scribe_shaders PROPERTIES FOLDER "Shaders")
|
||||
set_target_properties(compiled_shaders PROPERTIES FOLDER "Shaders")
|
||||
set_target_properties(reflected_shaders PROPERTIES FOLDER "Shaders")
|
||||
|
||||
configure_file(
|
||||
ShaderEnums.cpp.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/shaders/ShaderEnums.cpp
|
||||
)
|
||||
configure_file(
|
||||
ShaderEnums.h.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/shaders/ShaderEnums.h
|
||||
)
|
||||
configure_file(
|
||||
shaders.qrc.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/shaders.qrc
|
||||
)
|
||||
set(AUTOSCRIBE_SHADER_LIB_SRC "${CMAKE_CURRENT_BINARY_DIR}/shaders/ShaderEnums.h;${CMAKE_CURRENT_BINARY_DIR}/shaders/ShaderEnums.cpp")
|
||||
list(APPEND AUTOSCRIBE_SHADER_LIB_SRC ${COMPILED_SHADERS})
|
||||
set(QT_RESOURCES_FILE ${CMAKE_CURRENT_BINARY_DIR}/shaders.qrc)
|
||||
get_property(GLOBAL_SHADER_SOURCES GLOBAL PROPERTY GLOBAL_SHADER_SOURCES)
|
||||
list(REMOVE_DUPLICATES GLOBAL_SHADER_SOURCES)
|
||||
endmacro()
|
||||
|
|
|
@ -19,12 +19,8 @@ function(LINK_HIFI_LIBRARIES)
|
|||
endforeach()
|
||||
|
||||
foreach(HIFI_LIBRARY ${LIBRARIES_TO_LINK})
|
||||
|
||||
include_directories("${HIFI_LIBRARY_DIR}/${HIFI_LIBRARY}/src")
|
||||
include_directories("${CMAKE_BINARY_DIR}/libraries/${HIFI_LIBRARY}/shaders")
|
||||
|
||||
#add_dependencies(${TARGET_NAME} ${HIFI_LIBRARY})
|
||||
|
||||
include_directories("${CMAKE_BINARY_DIR}/libraries/${HIFI_LIBRARY}")
|
||||
# link the actual library - it is static so don't bubble it up
|
||||
target_link_libraries(${TARGET_NAME} ${HIFI_LIBRARY})
|
||||
endforeach()
|
||||
|
|
13
cmake/macros/TargetJson.cmake
Normal file
13
cmake/macros/TargetJson.cmake
Normal file
|
@ -0,0 +1,13 @@
|
|||
#
|
||||
# Created by Bradley Austin Davis on 2018/07/22
|
||||
# Copyright 2013-2018 High Fidelity, Inc.
|
||||
#
|
||||
# Distributed under the Apache License, Version 2.0.
|
||||
# See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
#
|
||||
macro(TARGET_JSON)
|
||||
add_dependency_external_projects(json)
|
||||
find_package(JSON REQUIRED)
|
||||
message("JSON_INCLUDE_DIRS ${JSON_INCLUDE_DIRS}")
|
||||
target_include_directories(${TARGET_NAME} PUBLIC ${JSON_INCLUDE_DIRS})
|
||||
endmacro()
|
19
cmake/modules/FindJSON.cmake
Normal file
19
cmake/modules/FindJSON.cmake
Normal file
|
@ -0,0 +1,19 @@
|
|||
#
|
||||
# Created by Bradley Austin Davis on 2018/07/22
|
||||
# Copyright 2013-2018 High Fidelity, Inc.
|
||||
#
|
||||
# Distributed under the Apache License, Version 2.0.
|
||||
# See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
#
|
||||
|
||||
# setup hints for JSON search
|
||||
include("${MACRO_DIR}/HifiLibrarySearchHints.cmake")
|
||||
hifi_library_search_hints("json")
|
||||
|
||||
# locate header
|
||||
find_path(JSON_INCLUDE_DIRS "json/json.hpp" HINTS ${JSON_SEARCH_DIRS})
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(JSON DEFAULT_MSG JSON_INCLUDE_DIRS)
|
||||
|
||||
mark_as_advanced(JSON_INCLUDE_DIRS JSON_SEARCH_DIRS)
|
|
@ -214,6 +214,7 @@ link_hifi_libraries(
|
|||
controllers plugins image trackers
|
||||
ui-plugins display-plugins input-plugins
|
||||
${PLATFORM_GL_BACKEND}
|
||||
shaders
|
||||
)
|
||||
|
||||
# include the binary directory of render-utils for shader includes
|
||||
|
|
|
@ -2703,8 +2703,6 @@ void Application::initializeGL() {
|
|||
// contexts
|
||||
_glWidget->makeCurrent();
|
||||
gpu::Context::init<gpu::gl::GLBackend>();
|
||||
qApp->setProperty(hifi::properties::gl::MAKE_PROGRAM_CALLBACK,
|
||||
QVariant::fromValue((void*)(&gpu::gl::GLBackend::makeProgram)));
|
||||
_glWidget->makeCurrent();
|
||||
_gpuContext = std::make_shared<gpu::Context>();
|
||||
|
||||
|
@ -4574,11 +4572,14 @@ void Application::idle() {
|
|||
_lastTimeUpdated.start();
|
||||
|
||||
// If the offscreen Ui has something active that is NOT the root, then assume it has keyboard focus.
|
||||
if (_keyboardDeviceHasFocus && offscreenUi && offscreenUi->getWindow()->activeFocusItem() != offscreenUi->getRootItem()) {
|
||||
_keyboardMouseDevice->pluginFocusOutEvent();
|
||||
_keyboardDeviceHasFocus = false;
|
||||
} else if (offscreenUi && offscreenUi->getWindow()->activeFocusItem() == offscreenUi->getRootItem()) {
|
||||
_keyboardDeviceHasFocus = true;
|
||||
if (offscreenUi && offscreenUi->getWindow()) {
|
||||
auto activeFocusItem = offscreenUi->getWindow()->activeFocusItem();
|
||||
if (_keyboardDeviceHasFocus && activeFocusItem != offscreenUi->getRootItem()) {
|
||||
_keyboardMouseDevice->pluginFocusOutEvent();
|
||||
_keyboardDeviceHasFocus = false;
|
||||
} else if (activeFocusItem == offscreenUi->getRootItem()) {
|
||||
_keyboardDeviceHasFocus = true;
|
||||
}
|
||||
}
|
||||
|
||||
checkChangeCursor();
|
||||
|
|
|
@ -12,11 +12,9 @@
|
|||
#include <StencilMaskPass.h>
|
||||
|
||||
#include <DependencyManager.h>
|
||||
#include <shaders/Shaders.h>
|
||||
|
||||
#include "ParabolaPick.h"
|
||||
|
||||
#include "render-utils/parabola_vert.h"
|
||||
#include "render-utils/parabola_frag.h"
|
||||
|
||||
const glm::vec4 ParabolaPointer::RenderState::ParabolaRenderItem::DEFAULT_PARABOLA_COLOR { 1.0f };
|
||||
const float ParabolaPointer::RenderState::ParabolaRenderItem::DEFAULT_PARABOLA_WIDTH { 0.01f };
|
||||
const bool ParabolaPointer::RenderState::ParabolaRenderItem::DEFAULT_PARABOLA_ISVISIBLEINSECONDARYCAMERA { false };
|
||||
|
@ -326,13 +324,7 @@ void ParabolaPointer::RenderState::ParabolaRenderItem::updateKey() {
|
|||
|
||||
const gpu::PipelinePointer ParabolaPointer::RenderState::ParabolaRenderItem::getParabolaPipeline() {
|
||||
if (!_parabolaPipeline || !_transparentParabolaPipeline) {
|
||||
auto vs = parabola_vert::getShader();
|
||||
auto ps = parabola_frag::getShader();
|
||||
gpu::ShaderPointer program = gpu::Shader::createProgram(vs, ps);
|
||||
|
||||
gpu::Shader::BindingSet slotBindings;
|
||||
slotBindings.insert(gpu::Shader::Binding(std::string("parabolaData"), 0));
|
||||
gpu::Shader::makeProgram(*program, slotBindings);
|
||||
gpu::ShaderPointer program = gpu::Shader::createProgram(shader::render_utils::program::parabola);
|
||||
|
||||
{
|
||||
auto state = std::make_shared<gpu::State>();
|
||||
|
|
|
@ -14,11 +14,7 @@
|
|||
|
||||
#include <StencilMaskPass.h>
|
||||
#include <GeometryCache.h>
|
||||
|
||||
#include "render-utils/drawWorkloadProxy_vert.h"
|
||||
#include "render-utils/drawWorkloadView_vert.h"
|
||||
#include "render-utils/drawWorkloadProxy_frag.h"
|
||||
#include "render-utils/drawWorkloadView_frag.h"
|
||||
#include <shaders/Shaders.h>
|
||||
|
||||
|
||||
void GameSpaceToRender::configure(const Config& config) {
|
||||
|
@ -149,14 +145,7 @@ void GameWorkloadRenderItem::setAllViews(const workload::Views& views) {
|
|||
|
||||
const gpu::PipelinePointer GameWorkloadRenderItem::getProxiesPipeline() {
|
||||
if (!_drawAllProxiesPipeline) {
|
||||
auto vs = drawWorkloadProxy_vert::getShader();
|
||||
auto ps = drawWorkloadProxy_frag::getShader();
|
||||
gpu::ShaderPointer program = gpu::Shader::createProgram(vs, ps);
|
||||
|
||||
gpu::Shader::BindingSet slotBindings;
|
||||
slotBindings.insert(gpu::Shader::Binding("workloadProxiesBuffer", 0));
|
||||
gpu::Shader::makeProgram(*program, slotBindings);
|
||||
|
||||
gpu::ShaderPointer program = gpu::Shader::createProgram(shader::render_utils::program::drawWorkloadProxy);
|
||||
auto state = std::make_shared<gpu::State>();
|
||||
state->setDepthTest(true, true, gpu::LESS_EQUAL);
|
||||
/* state->setBlendFunction(true,
|
||||
|
@ -173,15 +162,7 @@ const gpu::PipelinePointer GameWorkloadRenderItem::getProxiesPipeline() {
|
|||
|
||||
const gpu::PipelinePointer GameWorkloadRenderItem::getViewsPipeline() {
|
||||
if (!_drawAllViewsPipeline) {
|
||||
auto vs = drawWorkloadView_vert::getShader();
|
||||
auto ps = drawWorkloadView_frag::getShader();
|
||||
gpu::ShaderPointer program = gpu::Shader::createProgram(vs, ps);
|
||||
|
||||
gpu::Shader::BindingSet slotBindings;
|
||||
slotBindings.insert(gpu::Shader::Binding("workloadViewsBuffer", 1));
|
||||
slotBindings.insert(gpu::Shader::Binding("drawMeshBuffer", 0));
|
||||
gpu::Shader::makeProgram(*program, slotBindings);
|
||||
|
||||
gpu::ShaderPointer program = gpu::Shader::createProgram(shader::render_utils::program::drawWorkloadView);
|
||||
auto state = std::make_shared<gpu::State>();
|
||||
state->setDepthTest(true, true, gpu::LESS_EQUAL);
|
||||
/* state->setBlendFunction(true,
|
||||
|
@ -192,6 +173,7 @@ const gpu::PipelinePointer GameWorkloadRenderItem::getViewsPipeline() {
|
|||
state->setCullMode(gpu::State::CULL_NONE);
|
||||
_drawAllViewsPipeline = gpu::Pipeline::create(program, state);
|
||||
}
|
||||
|
||||
return _drawAllViewsPipeline;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
set(TARGET_NAME display-plugins)
|
||||
AUTOSCRIBE_SHADER_LIB(gpu display-plugins)
|
||||
setup_hifi_library(Gui)
|
||||
link_hifi_libraries(shared plugins ui-plugins gl ui render-utils ${PLATFORM_GL_BACKEND})
|
||||
link_hifi_libraries(shared shaders plugins ui-plugins gl ui render-utils ${PLATFORM_GL_BACKEND})
|
||||
include_hifi_library_headers(gpu)
|
||||
include_hifi_library_headers(model-networking)
|
||||
include_hifi_library_headers(networking)
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
struct TextureData {
|
||||
ivec2 textureSize;
|
||||
};
|
||||
|
||||
layout(std140, binding=0) uniform textureDataBuffer {
|
||||
TextureData textureData;
|
||||
};
|
||||
|
||||
layout(binding=0) uniform sampler2D colorMap;
|
||||
layout(location=0) in vec2 varTexCoord0;
|
||||
layout(location=0) out vec4 outFragColor;
|
||||
|
||||
void main(void) {
|
||||
ivec2 texCoord = ivec2(floor(varTexCoord0 * textureData.textureSize));
|
||||
texCoord.x /= 2;
|
||||
int row = int(floor(gl_FragCoord.y));
|
||||
if (row % 2 > 0) {
|
||||
texCoord.x += (textureData.textureSize.x / 2);
|
||||
}
|
||||
outFragColor = vec4(pow(texelFetch(colorMap, texCoord, 0).rgb, vec3(2.2)), 1.0);
|
||||
}
|
|
@ -30,7 +30,7 @@
|
|||
#include <gl/OffscreenGLCanvas.h>
|
||||
|
||||
#include <gpu/Texture.h>
|
||||
#include <gpu/StandardShaderLib.h>
|
||||
#include <shaders/Shaders.h>
|
||||
#include <gpu/gl/GLShared.h>
|
||||
#include <gpu/gl/GLBackend.h>
|
||||
#include <GeometryCache.h>
|
||||
|
@ -44,33 +44,6 @@
|
|||
#include "CompositorHelper.h"
|
||||
#include "Logging.h"
|
||||
|
||||
const char* SRGB_TO_LINEAR_FRAG = R"SCRIBE(
|
||||
|
||||
// OpenGLDisplayPlugin_present.frag
|
||||
|
||||
uniform sampler2D colorMap;
|
||||
|
||||
in vec2 varTexCoord0;
|
||||
|
||||
out vec4 outFragColor;
|
||||
|
||||
float sRGBFloatToLinear(float value) {
|
||||
const float SRGB_ELBOW = 0.04045;
|
||||
|
||||
return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);
|
||||
}
|
||||
|
||||
vec3 colorToLinearRGB(vec3 srgb) {
|
||||
return vec3(sRGBFloatToLinear(srgb.r), sRGBFloatToLinear(srgb.g), sRGBFloatToLinear(srgb.b));
|
||||
}
|
||||
|
||||
void main(void) {
|
||||
outFragColor.a = 1.0;
|
||||
outFragColor.rgb = colorToLinearRGB(texture(colorMap, varTexCoord0).rgb);
|
||||
}
|
||||
|
||||
)SCRIBE";
|
||||
|
||||
extern QThread* RENDER_THREAD;
|
||||
|
||||
class PresentThread : public QThread, public Dependency {
|
||||
|
@ -391,10 +364,7 @@ void OpenGLDisplayPlugin::customizeContext() {
|
|||
|
||||
if (!_presentPipeline) {
|
||||
{
|
||||
auto vs = gpu::StandardShaderLib::getDrawUnitQuadTexcoordVS();
|
||||
auto ps = gpu::StandardShaderLib::getDrawTexturePS();
|
||||
gpu::ShaderPointer program = gpu::Shader::createProgram(vs, ps);
|
||||
gpu::Shader::makeProgram(*program);
|
||||
gpu::ShaderPointer program = gpu::Shader::createProgram(shader::gpu::program::drawTexture);
|
||||
gpu::StatePointer state = gpu::StatePointer(new gpu::State());
|
||||
state->setDepthTest(gpu::State::DepthTest(false));
|
||||
state->setScissorEnable(true);
|
||||
|
@ -402,10 +372,7 @@ void OpenGLDisplayPlugin::customizeContext() {
|
|||
}
|
||||
|
||||
{
|
||||
auto vs = gpu::StandardShaderLib::getDrawUnitQuadTexcoordVS();
|
||||
auto ps = gpu::Shader::createPixel(std::string(SRGB_TO_LINEAR_FRAG));
|
||||
gpu::ShaderPointer program = gpu::Shader::createProgram(vs, ps);
|
||||
gpu::Shader::makeProgram(*program);
|
||||
gpu::ShaderPointer program = gpu::Shader::createProgram(shader::display_plugins::program::SrgbToLinear);
|
||||
gpu::StatePointer state = gpu::StatePointer(new gpu::State());
|
||||
state->setDepthTest(gpu::State::DepthTest(false));
|
||||
state->setScissorEnable(true);
|
||||
|
@ -413,10 +380,9 @@ void OpenGLDisplayPlugin::customizeContext() {
|
|||
}
|
||||
|
||||
{
|
||||
auto vs = gpu::StandardShaderLib::getDrawUnitQuadTexcoordVS();
|
||||
auto ps = gpu::StandardShaderLib::getDrawTexturePS();
|
||||
auto vs = gpu::Shader::createVertex(shader::gpu::vertex::DrawUnitQuadTexcoord);
|
||||
auto ps = gpu::Shader::createPixel(shader::gpu::fragment::DrawTexture);
|
||||
gpu::ShaderPointer program = gpu::Shader::createProgram(vs, ps);
|
||||
gpu::Shader::makeProgram(*program);
|
||||
gpu::StatePointer state = gpu::StatePointer(new gpu::State());
|
||||
state->setDepthTest(gpu::State::DepthTest(false));
|
||||
state->setBlendFunction(true,
|
||||
|
@ -426,10 +392,9 @@ void OpenGLDisplayPlugin::customizeContext() {
|
|||
}
|
||||
|
||||
{
|
||||
auto vs = gpu::StandardShaderLib::getDrawUnitQuadTexcoordVS();
|
||||
auto ps = gpu::StandardShaderLib::getDrawTextureMirroredXPS();
|
||||
auto vs = gpu::Shader::createVertex(shader::gpu::vertex::DrawUnitQuadTexcoord);
|
||||
auto ps = gpu::Shader::createPixel(shader::gpu::fragment::DrawTextureMirroredX);
|
||||
gpu::ShaderPointer program = gpu::Shader::createProgram(vs, ps);
|
||||
gpu::Shader::makeProgram(*program);
|
||||
gpu::StatePointer state = gpu::StatePointer(new gpu::State());
|
||||
state->setDepthTest(gpu::State::DepthTest(false));
|
||||
state->setBlendFunction(true,
|
||||
|
@ -439,10 +404,9 @@ void OpenGLDisplayPlugin::customizeContext() {
|
|||
}
|
||||
|
||||
{
|
||||
auto vs = gpu::StandardShaderLib::getDrawTransformUnitQuadVS();
|
||||
auto ps = gpu::StandardShaderLib::getDrawTexturePS();
|
||||
auto vs = gpu::Shader::createVertex(shader::gpu::vertex::DrawTransformUnitQuad);
|
||||
auto ps = gpu::Shader::createPixel(shader::gpu::fragment::DrawTexture);
|
||||
gpu::ShaderPointer program = gpu::Shader::createProgram(vs, ps);
|
||||
gpu::Shader::makeProgram(*program);
|
||||
gpu::StatePointer state = gpu::StatePointer(new gpu::State());
|
||||
state->setDepthTest(gpu::State::DepthTest(false));
|
||||
state->setBlendFunction(true,
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
// OpenGLDisplayPlugin_present.frag
|
||||
|
||||
layout(binding = 0) uniform sampler2D colorMap;
|
||||
|
||||
layout(location = 0) in vec2 varTexCoord0;
|
||||
|
||||
layout(location = 0) out vec4 outFragColor;
|
||||
|
||||
float sRGBFloatToLinear(float value) {
|
||||
const float SRGB_ELBOW = 0.04045;
|
||||
|
||||
return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);
|
||||
}
|
||||
|
||||
vec3 colorToLinearRGB(vec3 srgb) {
|
||||
return vec3(sRGBFloatToLinear(srgb.r), sRGBFloatToLinear(srgb.g), sRGBFloatToLinear(srgb.b));
|
||||
}
|
||||
|
||||
void main(void) {
|
||||
outFragColor.a = 1.0;
|
||||
outFragColor.rgb = colorToLinearRGB(texture(colorMap, varTexCoord0).rgb);
|
||||
}
|
|
@ -24,8 +24,8 @@
|
|||
#include <gl/GLWidget.h>
|
||||
#include <shared/NsightHelpers.h>
|
||||
#include <gpu/Context.h>
|
||||
#include <gpu/StandardShaderLib.h>
|
||||
#include <gpu/gl/GLBackend.h>
|
||||
#include <shaders/Shaders.h>
|
||||
|
||||
#include <TextureCache.h>
|
||||
#include <PathUtils.h>
|
||||
|
@ -34,8 +34,6 @@
|
|||
#include "../CompositorHelper.h"
|
||||
|
||||
#include "DesktopPreviewProvider.h"
|
||||
#include "render-utils/hmd_ui_vert.h"
|
||||
#include "render-utils/hmd_ui_frag.h"
|
||||
|
||||
static const QString MONO_PREVIEW = "Mono Preview";
|
||||
static const QString DISABLE_PREVIEW = "Disable Preview";
|
||||
|
@ -409,12 +407,7 @@ void HmdDisplayPlugin::HUDRenderer::build() {
|
|||
|
||||
void HmdDisplayPlugin::HUDRenderer::updatePipeline() {
|
||||
if (!pipeline) {
|
||||
auto vs = hmd_ui_vert::getShader();
|
||||
auto ps = hmd_ui_frag::getShader();
|
||||
auto program = gpu::Shader::createProgram(vs, ps);
|
||||
gpu::Shader::makeProgram(*program, gpu::Shader::BindingSet());
|
||||
uniformsLocation = program->getUniformBuffers().findLocation("hudBuffer");
|
||||
|
||||
auto program = gpu::Shader::createProgram(shader::render_utils::program::hmd_ui);
|
||||
gpu::StatePointer state = gpu::StatePointer(new gpu::State());
|
||||
state->setDepthTest(gpu::State::DepthTest(true, true, gpu::LESS_EQUAL));
|
||||
state->setBlendFunction(true,
|
||||
|
@ -437,9 +430,8 @@ std::function<void(gpu::Batch&, const gpu::TexturePointer&, bool mirror)> HmdDis
|
|||
batch.setInputBuffer(gpu::Stream::POSITION, posView);
|
||||
batch.setInputBuffer(gpu::Stream::TEXCOORD, uvView);
|
||||
batch.setIndexBuffer(gpu::UINT16, indices, 0);
|
||||
|
||||
uniformsBuffer->setSubData(0, uniforms);
|
||||
batch.setUniformBuffer(uniformsLocation, uniformsBuffer);
|
||||
batch.setUniformBuffer(0, uniformsBuffer);
|
||||
|
||||
auto compositorHelper = DependencyManager::get<CompositorHelper>();
|
||||
glm::mat4 modelTransform = compositorHelper->getUiTransform();
|
||||
|
|
|
@ -102,7 +102,6 @@ private:
|
|||
gpu::BufferPointer indices;
|
||||
uint32_t indexCount { 0 };
|
||||
gpu::PipelinePointer pipeline;
|
||||
int32_t uniformsLocation { -1 };
|
||||
|
||||
gpu::BufferPointer uniformsBuffer;
|
||||
|
||||
|
|
|
@ -8,48 +8,17 @@
|
|||
|
||||
#include "InterleavedStereoDisplayPlugin.h"
|
||||
|
||||
#include <gpu/StandardShaderLib.h>
|
||||
#include <gpu/Pipeline.h>
|
||||
#include <gpu/Batch.h>
|
||||
#include <gpu/Context.h>
|
||||
|
||||
static const char* INTERLEAVED_SRGB_TO_LINEAR_FRAG = R"SCRIBE(
|
||||
|
||||
struct TextureData {
|
||||
ivec2 textureSize;
|
||||
};
|
||||
|
||||
layout(std140) uniform textureDataBuffer {
|
||||
TextureData textureData;
|
||||
};
|
||||
|
||||
uniform sampler2D colorMap;
|
||||
|
||||
in vec2 varTexCoord0;
|
||||
|
||||
out vec4 outFragColor;
|
||||
|
||||
void main(void) {
|
||||
ivec2 texCoord = ivec2(floor(varTexCoord0 * textureData.textureSize));
|
||||
texCoord.x /= 2;
|
||||
int row = int(floor(gl_FragCoord.y));
|
||||
if (row % 2 > 0) {
|
||||
texCoord.x += (textureData.textureSize.x / 2);
|
||||
}
|
||||
outFragColor = vec4(pow(texelFetch(colorMap, texCoord, 0).rgb, vec3(2.2)), 1.0);
|
||||
}
|
||||
|
||||
)SCRIBE";
|
||||
#include <shaders/Shaders.h>
|
||||
|
||||
const QString InterleavedStereoDisplayPlugin::NAME("3D TV - Interleaved");
|
||||
|
||||
void InterleavedStereoDisplayPlugin::customizeContext() {
|
||||
StereoDisplayPlugin::customizeContext();
|
||||
if (!_interleavedPresentPipeline) {
|
||||
auto vs = gpu::StandardShaderLib::getDrawUnitQuadTexcoordVS();
|
||||
auto ps = gpu::Shader::createPixel(std::string(INTERLEAVED_SRGB_TO_LINEAR_FRAG));
|
||||
gpu::ShaderPointer program = gpu::Shader::createProgram(vs, ps);
|
||||
gpu::Shader::makeProgram(*program);
|
||||
gpu::ShaderPointer program = gpu::Shader::createProgram(shader::display_plugins::program::InterleavedSrgbToLinear);
|
||||
gpu::StatePointer state = gpu::StatePointer(new gpu::State());
|
||||
state->setDepthTest(gpu::State::DepthTest(false));
|
||||
_interleavedPresentPipeline = gpu::Pipeline::create(program, state);
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
set(TARGET_NAME entities-renderer)
|
||||
AUTOSCRIBE_SHADER_LIB(gpu graphics procedural render render-utils)
|
||||
setup_hifi_library(Network Script)
|
||||
link_hifi_libraries(shared workload gpu procedural graphics model-networking script-engine render render-utils image qml ui pointers)
|
||||
link_hifi_libraries(shared workload gpu shaders procedural graphics model-networking script-engine render render-utils image qml ui pointers)
|
||||
include_hifi_library_headers(networking)
|
||||
include_hifi_library_headers(gl)
|
||||
include_hifi_library_headers(ktx)
|
||||
|
@ -18,3 +17,4 @@ include_hifi_library_headers(graphics-scripting) # for Forward.h
|
|||
|
||||
target_bullet()
|
||||
target_polyvox()
|
||||
|
||||
|
|
|
@ -13,9 +13,8 @@
|
|||
#include <StencilMaskPass.h>
|
||||
|
||||
#include <GeometryCache.h>
|
||||
#include <shaders/Shaders.h>
|
||||
|
||||
#include "textured_particle_vert.h"
|
||||
#include "textured_particle_frag.h"
|
||||
|
||||
using namespace render;
|
||||
using namespace render::entities;
|
||||
|
@ -23,8 +22,6 @@ using namespace render::entities;
|
|||
static uint8_t CUSTOM_PIPELINE_NUMBER = 0;
|
||||
static gpu::Stream::FormatPointer _vertexFormat;
|
||||
static std::weak_ptr<gpu::Pipeline> _texturedPipeline;
|
||||
// FIXME: This is interfering with the uniform buffers in DeferredLightingEffect.cpp, so use 12 to avoid collisions
|
||||
static int32_t PARTICLE_UNIFORM_SLOT { 12 };
|
||||
|
||||
static ShapePipelinePointer shapePipelineFactory(const ShapePlumber& plumber, const ShapeKey& key, gpu::Batch& batch) {
|
||||
auto texturedPipeline = _texturedPipeline.lock();
|
||||
|
@ -36,17 +33,8 @@ static ShapePipelinePointer shapePipelineFactory(const ShapePlumber& plumber, co
|
|||
gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE);
|
||||
PrepareStencil::testMask(*state);
|
||||
|
||||
auto vertShader = textured_particle_vert::getShader();
|
||||
auto fragShader = textured_particle_frag::getShader();
|
||||
|
||||
auto program = gpu::Shader::createProgram(vertShader, fragShader);
|
||||
auto program = gpu::Shader::createProgram(shader::entities_renderer::program::textured_particle);
|
||||
_texturedPipeline = texturedPipeline = gpu::Pipeline::create(program, state);
|
||||
|
||||
batch.runLambda([program] {
|
||||
gpu::Shader::BindingSet slotBindings;
|
||||
slotBindings.insert(gpu::Shader::Binding(std::string("particleBuffer"), PARTICLE_UNIFORM_SLOT));
|
||||
gpu::Shader::makeProgram(*program, slotBindings);
|
||||
});
|
||||
}
|
||||
|
||||
return std::make_shared<render::ShapePipeline>(texturedPipeline, nullptr, nullptr, nullptr);
|
||||
|
@ -346,7 +334,7 @@ void ParticleEffectEntityRenderer::doRender(RenderArgs* args) {
|
|||
transform.setRotation(_renderTransform.getRotation());
|
||||
});
|
||||
batch.setModelTransform(transform);
|
||||
batch.setUniformBuffer(PARTICLE_UNIFORM_SLOT, _uniformBuffer);
|
||||
batch.setUniformBuffer(0, _uniformBuffer);
|
||||
batch.setInputFormat(_vertexFormat);
|
||||
batch.setInputBuffer(0, _particleBuffer, 0, sizeof(GpuParticle));
|
||||
|
||||
|
|
|
@ -17,18 +17,13 @@
|
|||
#include <TextureCache.h>
|
||||
#include <PathUtils.h>
|
||||
#include <PerfStat.h>
|
||||
#include <shaders/Shaders.h>
|
||||
|
||||
//#define POLYLINE_ENTITY_USE_FADE_EFFECT
|
||||
#ifdef POLYLINE_ENTITY_USE_FADE_EFFECT
|
||||
# include <FadeEffect.h>
|
||||
#endif
|
||||
|
||||
#include "paintStroke_vert.h"
|
||||
#include "paintStroke_frag.h"
|
||||
|
||||
#include "paintStroke_fade_vert.h"
|
||||
#include "paintStroke_fade_frag.h"
|
||||
|
||||
using namespace render;
|
||||
using namespace render::entities;
|
||||
|
||||
|
@ -48,29 +43,12 @@ struct PolyLineUniforms {
|
|||
|
||||
static render::ShapePipelinePointer shapePipelineFactory(const render::ShapePlumber& plumber, const render::ShapeKey& key, gpu::Batch& batch) {
|
||||
if (!polylinePipeline) {
|
||||
auto VS = paintStroke_vert::getShader();
|
||||
auto PS = paintStroke_frag::getShader();
|
||||
gpu::ShaderPointer program = gpu::Shader::createProgram(VS, PS);
|
||||
gpu::ShaderPointer program = gpu::Shader::createProgram(shader::entities_renderer::program::paintStroke);
|
||||
#ifdef POLYLINE_ENTITY_USE_FADE_EFFECT
|
||||
auto fadeVS = gpu::Shader::createVertex(std::string(paintStroke_fade_vert));
|
||||
auto fadePS = gpu::Shader::createPixel(std::string(paintStroke_fade_frag));
|
||||
gpu::ShaderPointer fadeProgram = gpu::Shader::createProgram(fadeVS, fadePS);
|
||||
#endif
|
||||
batch.runLambda([program
|
||||
#ifdef POLYLINE_ENTITY_USE_FADE_EFFECT
|
||||
, fadeProgram
|
||||
#endif
|
||||
] {
|
||||
gpu::Shader::BindingSet slotBindings;
|
||||
slotBindings.insert(gpu::Shader::Binding(std::string("originalTexture"), PAINTSTROKE_TEXTURE_SLOT));
|
||||
slotBindings.insert(gpu::Shader::Binding(std::string("polyLineBuffer"), PAINTSTROKE_UNIFORM_SLOT));
|
||||
gpu::Shader::makeProgram(*program, slotBindings);
|
||||
#ifdef POLYLINE_ENTITY_USE_FADE_EFFECT
|
||||
slotBindings.insert(gpu::Shader::Binding(std::string("fadeMaskMap"), PAINTSTROKE_TEXTURE_SLOT + 1));
|
||||
slotBindings.insert(gpu::Shader::Binding(std::string("fadeParametersBuffer"), PAINTSTROKE_UNIFORM_SLOT + 1));
|
||||
gpu::Shader::makeProgram(*fadeProgram, slotBindings);
|
||||
#endif
|
||||
});
|
||||
gpu::StatePointer state = gpu::StatePointer(new gpu::State());
|
||||
state->setDepthTest(true, true, gpu::LESS_EQUAL);
|
||||
PrepareStencil::testMask(*state);
|
||||
|
|
|
@ -25,14 +25,15 @@
|
|||
#include <EntityEditPacketSender.h>
|
||||
#include <PhysicalEntitySimulation.h>
|
||||
#include <StencilMaskPass.h>
|
||||
#include <graphics/ShaderConstants.h>
|
||||
#include <render/ShapePipeline.h>
|
||||
|
||||
#include "entities-renderer/ShaderConstants.h"
|
||||
|
||||
#include <shaders/Shaders.h>
|
||||
|
||||
#include "EntityTreeRenderer.h"
|
||||
|
||||
#include "polyvox_vert.h"
|
||||
#include "polyvox_frag.h"
|
||||
#include "polyvox_fade_vert.h"
|
||||
#include "polyvox_fade_frag.h"
|
||||
|
||||
#ifdef POLYVOX_ENTITY_USE_FADE_EFFECT
|
||||
# include <FadeEffect.h>
|
||||
#endif
|
||||
|
@ -72,11 +73,6 @@
|
|||
|
||||
#include "EntityTreeRenderer.h"
|
||||
|
||||
#include "polyvox_vert.h"
|
||||
#include "polyvox_frag.h"
|
||||
#include "polyvox_fade_vert.h"
|
||||
#include "polyvox_fade_frag.h"
|
||||
|
||||
#include "RenderablePolyVoxEntityItem.h"
|
||||
#include "EntityEditPacketSender.h"
|
||||
#include "PhysicalEntitySimulation.h"
|
||||
|
@ -1564,7 +1560,6 @@ scriptable::ScriptableModelBase RenderablePolyVoxEntityItem::getScriptableModel(
|
|||
using namespace render;
|
||||
using namespace render::entities;
|
||||
|
||||
static const int MATERIAL_GPU_SLOT { 3 };
|
||||
static uint8_t CUSTOM_PIPELINE_NUMBER;
|
||||
static gpu::PipelinePointer _pipelines[2];
|
||||
static gpu::PipelinePointer _wireframePipelines[2];
|
||||
|
@ -1572,17 +1567,8 @@ static gpu::Stream::FormatPointer _vertexFormat;
|
|||
|
||||
ShapePipelinePointer shapePipelineFactory(const ShapePlumber& plumber, const ShapeKey& key, gpu::Batch& batch) {
|
||||
if (!_pipelines[0]) {
|
||||
gpu::ShaderPointer vertexShaders[2] = { polyvox_vert::getShader(), polyvox_fade_vert::getShader() };
|
||||
gpu::ShaderPointer pixelShaders[2] = { polyvox_frag::getShader(), polyvox_fade_frag::getShader() };
|
||||
|
||||
gpu::Shader::BindingSet slotBindings;
|
||||
slotBindings.insert(gpu::Shader::Binding(std::string("materialBuffer"), MATERIAL_GPU_SLOT));
|
||||
slotBindings.insert(gpu::Shader::Binding(std::string("xMap"), 0));
|
||||
slotBindings.insert(gpu::Shader::Binding(std::string("yMap"), 1));
|
||||
slotBindings.insert(gpu::Shader::Binding(std::string("zMap"), 2));
|
||||
#ifdef POLYVOX_ENTITY_USE_FADE_EFFECT
|
||||
slotBindings.insert(gpu::Shader::Binding(std::string("fadeMaskMap"), 3));
|
||||
#endif
|
||||
using namespace shader::entities_renderer::program;
|
||||
int programsIds[2] = { polyvox, polyvox_fade };
|
||||
|
||||
auto state = std::make_shared<gpu::State>();
|
||||
state->setCullMode(gpu::State::CULL_BACK);
|
||||
|
@ -1597,12 +1583,7 @@ ShapePipelinePointer shapePipelineFactory(const ShapePlumber& plumber, const Sha
|
|||
|
||||
// Two sets of pipelines: normal and fading
|
||||
for (auto i = 0; i < 2; i++) {
|
||||
gpu::ShaderPointer program = gpu::Shader::createProgram(vertexShaders[i], pixelShaders[i]);
|
||||
|
||||
batch.runLambda([program, slotBindings] {
|
||||
gpu::Shader::makeProgram(*program, slotBindings);
|
||||
});
|
||||
|
||||
gpu::ShaderPointer program = gpu::Shader::createProgram(programsIds[i]);
|
||||
_pipelines[i] = gpu::Pipeline::create(program, state);
|
||||
_wireframePipelines[i] = gpu::Pipeline::create(program, wireframeState);
|
||||
}
|
||||
|
@ -1737,8 +1718,7 @@ void PolyVoxEntityRenderer::doRender(RenderArgs* args) {
|
|||
}
|
||||
}
|
||||
|
||||
int voxelVolumeSizeLocation = args->_shapePipeline->pipeline->getProgram()->getUniforms().findLocation("voxelVolumeSize");
|
||||
batch._glUniform3f(voxelVolumeSizeLocation, _lastVoxelVolumeSize.x, _lastVoxelVolumeSize.y, _lastVoxelVolumeSize.z);
|
||||
batch._glUniform3f(entities_renderer::slot::uniform::PolyvoxVoxelSize, _lastVoxelVolumeSize.x, _lastVoxelVolumeSize.y, _lastVoxelVolumeSize.z);
|
||||
batch.drawIndexed(gpu::TRIANGLES, (gpu::uint32)_mesh->getNumIndices(), 0);
|
||||
}
|
||||
|
||||
|
|
|
@ -15,12 +15,7 @@
|
|||
#include <StencilMaskPass.h>
|
||||
#include <GeometryCache.h>
|
||||
#include <PerfStat.h>
|
||||
|
||||
#include "render-utils/simple_vert.h"
|
||||
#include "render-utils/simple_frag.h"
|
||||
#include "render-utils/simple_transparent_frag.h"
|
||||
#include "render-utils/forward_simple_frag.h"
|
||||
#include "render-utils/forward_simple_transparent_frag.h"
|
||||
#include <shaders/Shaders.h>
|
||||
|
||||
#include "RenderPipelines.h"
|
||||
|
||||
|
@ -37,12 +32,12 @@ static const float SPHERE_ENTITY_SCALE = 0.5f;
|
|||
|
||||
|
||||
ShapeEntityRenderer::ShapeEntityRenderer(const EntityItemPointer& entity) : Parent(entity) {
|
||||
_procedural._vertexSource = simple_vert::getSource();
|
||||
_procedural._vertexSource = gpu::Shader::getVertexShaderSource(shader::render_utils::vertex::simple);
|
||||
// FIXME: Setup proper uniform slots and use correct pipelines for forward rendering
|
||||
_procedural._opaquefragmentSource = simple_frag::getSource();
|
||||
_procedural._opaquefragmentSource = gpu::Shader::getFragmentShaderSource(shader::render_utils::fragment::simple);
|
||||
// FIXME: Transparent procedural entities only seem to work if they use the opaque pipelines
|
||||
//_procedural._transparentfragmentSource = simple_transparent_frag::getSource();
|
||||
_procedural._transparentfragmentSource = simple_frag::getSource();
|
||||
_procedural._transparentfragmentSource = _procedural._opaquefragmentSource;
|
||||
_procedural._opaqueState->setCullMode(gpu::State::CULL_NONE);
|
||||
_procedural._opaqueState->setDepthTest(true, true, gpu::LESS_EQUAL);
|
||||
PrepareStencil::testMaskDrawShape(*_procedural._opaqueState);
|
||||
|
|
|
@ -0,0 +1,61 @@
|
|||
// <!
|
||||
// Created by Bradley Austin Davis on 2018/05/25
|
||||
// Copyright 2013-2018 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
// !>
|
||||
|
||||
// <@if not ENTITIES_SHADER_CONSTANTS_H@>
|
||||
// <@def ENTITIES_SHADER_CONSTANTS_H@>
|
||||
|
||||
// Hack comment to absorb the extra '//' scribe prepends
|
||||
|
||||
#ifndef ENTITIES_SHADER_CONSTANTS_H
|
||||
#define ENTITIES_SHADER_CONSTANTS_H
|
||||
|
||||
// Polyvox
|
||||
#define ENTITIES_UNIFORM_POLYVOX_VOXEL_SIZE 0
|
||||
#define ENTITIES_TEXTURE_POLYVOX_XMAP 0
|
||||
#define ENTITIES_TEXTURE_POLYVOX_YMAP 1
|
||||
#define ENTITIES_TEXTURE_POLYVOX_ZMAP 2
|
||||
|
||||
|
||||
|
||||
// <!
|
||||
|
||||
namespace entities_renderer { namespace slot {
|
||||
|
||||
namespace uniform {
|
||||
enum Uniform {
|
||||
PolyvoxVoxelSize = ENTITIES_UNIFORM_POLYVOX_VOXEL_SIZE,
|
||||
};
|
||||
}
|
||||
|
||||
namespace buffer {
|
||||
enum Buffer {
|
||||
};
|
||||
} // namespace buffer
|
||||
|
||||
namespace texture {
|
||||
enum Texture {
|
||||
PolyvoxXMap = ENTITIES_TEXTURE_POLYVOX_XMAP,
|
||||
PolyvoxYMap = ENTITIES_TEXTURE_POLYVOX_YMAP,
|
||||
PolyvoxZMap = ENTITIES_TEXTURE_POLYVOX_ZMAP,
|
||||
};
|
||||
} // namespace texture
|
||||
|
||||
} } // namespace entities::slot
|
||||
|
||||
// !>
|
||||
// Hack Comment
|
||||
|
||||
#endif // ENTITIES_SHADER_CONSTANTS_H
|
||||
|
||||
// <@if 1@>
|
||||
// Trigger Scribe include
|
||||
// <@endif@> <!def that !>
|
||||
|
||||
// <@endif@>
|
||||
|
||||
// Hack Comment
|
|
@ -16,18 +16,18 @@
|
|||
|
||||
|
||||
// the albedo texture
|
||||
uniform sampler2D originalTexture;
|
||||
layout(binding=0) uniform sampler2D originalTexture;
|
||||
|
||||
// the interpolated normal
|
||||
in vec3 interpolatedNormal;
|
||||
in vec2 varTexcoord;
|
||||
in vec4 varColor;
|
||||
layout(location=0) in vec3 interpolatedNormal;
|
||||
layout(location=1) in vec2 varTexcoord;
|
||||
layout(location=2) in vec4 varColor;
|
||||
|
||||
struct PolyLineUniforms {
|
||||
vec3 color;
|
||||
};
|
||||
|
||||
uniform polyLineBuffer {
|
||||
layout(binding=0) uniform polyLineBuffer {
|
||||
PolyLineUniforms polyline;
|
||||
};
|
||||
|
||||
|
|
|
@ -18,12 +18,12 @@
|
|||
<$declareStandardTransform()$>
|
||||
|
||||
// the interpolated normal
|
||||
out vec3 interpolatedNormal;
|
||||
layout(location=0) out vec3 interpolatedNormal;
|
||||
|
||||
//the diffuse texture
|
||||
out vec2 varTexcoord;
|
||||
layout(location=1) out vec2 varTexcoord;
|
||||
|
||||
out vec4 varColor;
|
||||
layout(location=2) out vec4 varColor;
|
||||
|
||||
void main(void) {
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<$VERSION_HEADER$>
|
||||
// Generated on <$_SCRIBE_DATE$>
|
||||
//
|
||||
// paintStroke_fade.slf
|
||||
// paintStroke_fade.frag
|
||||
// fragment shader
|
||||
//
|
||||
// Created by Olivier Prat on 19/07/17.
|
||||
|
@ -18,19 +18,19 @@
|
|||
<$declareFadeFragment()$>
|
||||
|
||||
// the albedo texture
|
||||
uniform sampler2D originalTexture;
|
||||
layout(binding=0) uniform sampler2D originalTexture;
|
||||
|
||||
// the interpolated normal
|
||||
in vec3 interpolatedNormal;
|
||||
in vec2 varTexcoord;
|
||||
in vec4 varColor;
|
||||
in vec4 _worldPosition;
|
||||
layout(location=0) in vec3 interpolatedNormal;
|
||||
layout(location=1) in vec2 varTexcoord;
|
||||
layout(location=2) in vec4 varColor;
|
||||
layout(location=3) in vec4 _worldPosition;
|
||||
|
||||
struct PolyLineUniforms {
|
||||
vec3 color;
|
||||
};
|
||||
|
||||
uniform polyLineBuffer {
|
||||
layout(binding=0) uniform polyLineBuffer {
|
||||
PolyLineUniforms polyline;
|
||||
};
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<$VERSION_HEADER$>
|
||||
// Generated on <$_SCRIBE_DATE$>
|
||||
//
|
||||
// paintStroke_fade.slv
|
||||
// paintStroke_fade.vert
|
||||
// vertex shader
|
||||
//
|
||||
// Created by Olivier Prat on 19/07/17.
|
||||
|
@ -18,13 +18,13 @@
|
|||
<$declareStandardTransform()$>
|
||||
|
||||
// the interpolated normal
|
||||
out vec3 interpolatedNormal;
|
||||
layout(location=0) out vec3 interpolatedNormal;
|
||||
|
||||
//the diffuse texture
|
||||
out vec2 varTexcoord;
|
||||
layout(location=1) out vec2 varTexcoord;
|
||||
|
||||
out vec4 varColor;
|
||||
out vec4 _worldPosition;
|
||||
layout(location=2) out vec4 varColor;
|
||||
layout(location=3) out vec4 _worldPosition;
|
||||
|
||||
void main(void) {
|
||||
|
||||
|
|
|
@ -13,15 +13,17 @@
|
|||
|
||||
<@include graphics/Material.slh@>
|
||||
<@include DeferredBufferWrite.slh@>
|
||||
<@include render-utils/ShaderConstants.h@>
|
||||
<@include entities-renderer/ShaderConstants.h@>
|
||||
|
||||
in vec3 _normal;
|
||||
in vec4 _position;
|
||||
in vec4 _worldPosition;
|
||||
layout(location=RENDER_UTILS_ATTR_NORMAL_MS) in vec3 _normal;
|
||||
layout(location=RENDER_UTILS_ATTR_POSITION_MS) in vec4 _position;
|
||||
layout(location=RENDER_UTILS_ATTR_POSITION_WS) in vec4 _worldPosition;
|
||||
|
||||
uniform sampler2D xMap;
|
||||
uniform sampler2D yMap;
|
||||
uniform sampler2D zMap;
|
||||
uniform vec3 voxelVolumeSize;
|
||||
layout(binding=ENTITIES_TEXTURE_POLYVOX_XMAP) uniform sampler2D xMap;
|
||||
layout(binding=ENTITIES_TEXTURE_POLYVOX_YMAP) uniform sampler2D yMap;
|
||||
layout(binding=ENTITIES_TEXTURE_POLYVOX_ZMAP) uniform sampler2D zMap;
|
||||
layout(location=ENTITIES_UNIFORM_POLYVOX_VOXEL_SIZE) uniform vec3 voxelVolumeSize;
|
||||
|
||||
void main(void) {
|
||||
vec3 worldNormal = cross(dFdy(_worldPosition.xyz), dFdx(_worldPosition.xyz));
|
||||
|
|
|
@ -11,14 +11,14 @@
|
|||
//
|
||||
|
||||
<@include gpu/Inputs.slh@>
|
||||
|
||||
<@include gpu/Transform.slh@>
|
||||
<@include render-utils/ShaderConstants.h@>
|
||||
|
||||
<$declareStandardTransform()$>
|
||||
|
||||
out vec4 _position;
|
||||
out vec4 _worldPosition;
|
||||
out vec3 _normal;
|
||||
layout(location=RENDER_UTILS_ATTR_POSITION_MS) out vec4 _position;
|
||||
layout(location=RENDER_UTILS_ATTR_POSITION_WS) out vec4 _worldPosition;
|
||||
layout(location=RENDER_UTILS_ATTR_NORMAL_MS) out vec3 _normal;
|
||||
|
||||
void main(void) {
|
||||
// standard transform
|
||||
|
|
|
@ -13,18 +13,21 @@
|
|||
|
||||
<@include graphics/Material.slh@>
|
||||
<@include DeferredBufferWrite.slh@>
|
||||
<@include render-utils/ShaderConstants.h@>
|
||||
<@include entities-renderer/ShaderConstants.h@>
|
||||
|
||||
<@include Fade.slh@>
|
||||
|
||||
in vec3 _normal;
|
||||
in vec4 _position;
|
||||
in vec4 _worldPosition;
|
||||
in vec4 _worldFadePosition;
|
||||
layout(location=RENDER_UTILS_ATTR_NORMAL_MS) in vec3 _normal;
|
||||
layout(location=RENDER_UTILS_ATTR_POSITION_MS) in vec4 _position;
|
||||
layout(location=RENDER_UTILS_ATTR_POSITION_WS) in vec4 _worldPosition;
|
||||
layout(location=RENDER_UTILS_ATTR_POSITION_ES) in vec4 _worldFadePosition;
|
||||
|
||||
uniform sampler2D xMap;
|
||||
uniform sampler2D yMap;
|
||||
uniform sampler2D zMap;
|
||||
uniform vec3 voxelVolumeSize;
|
||||
layout(binding=ENTITIES_TEXTURE_POLYVOX_XMAP) uniform sampler2D xMap;
|
||||
layout(binding=ENTITIES_TEXTURE_POLYVOX_YMAP) uniform sampler2D yMap;
|
||||
layout(binding=ENTITIES_TEXTURE_POLYVOX_ZMAP) uniform sampler2D zMap;
|
||||
|
||||
layout(location=ENTITIES_UNIFORM_POLYVOX_VOXEL_SIZE) uniform vec3 voxelVolumeSize;
|
||||
|
||||
// Declare after all samplers to prevent sampler location mix up with voxel shading (sampler locations are hardcoded in RenderablePolyVoxEntityItem)
|
||||
<$declareFadeFragment()$>
|
||||
|
|
|
@ -12,15 +12,15 @@
|
|||
//
|
||||
|
||||
<@include gpu/Inputs.slh@>
|
||||
|
||||
<@include gpu/Transform.slh@>
|
||||
<@include render-utils/ShaderConstants.h@>
|
||||
|
||||
<$declareStandardTransform()$>
|
||||
|
||||
out vec4 _position;
|
||||
out vec4 _worldPosition;
|
||||
out vec4 _worldFadePosition;
|
||||
out vec3 _normal;
|
||||
layout(location=RENDER_UTILS_ATTR_POSITION_MS) out vec4 _position;
|
||||
layout(location=RENDER_UTILS_ATTR_POSITION_WS) out vec4 _worldPosition;
|
||||
layout(location=RENDER_UTILS_ATTR_NORMAL_MS) out vec3 _normal;
|
||||
layout(location=RENDER_UTILS_ATTR_POSITION_ES) out vec4 _worldFadePosition;
|
||||
|
||||
void main(void) {
|
||||
// standard transform
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
<@include gpu/Config.slh@>
|
||||
<$VERSION_HEADER$>
|
||||
// Generated on <$_SCRIBE_DATE$>
|
||||
// fragment shader
|
||||
//
|
||||
// textured_particle.frag
|
||||
//
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
|
@ -9,12 +10,12 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
uniform sampler2D colorMap;
|
||||
layout(binding=0) uniform sampler2D colorMap;
|
||||
|
||||
in vec4 varColor;
|
||||
in vec2 varTexcoord;
|
||||
layout(location=0) in vec4 varColor;
|
||||
layout(location=1) in vec2 varTexcoord;
|
||||
|
||||
out vec4 outFragColor;
|
||||
layout(location=0) out vec4 outFragColor;
|
||||
|
||||
void main(void) {
|
||||
outFragColor = texture(colorMap, varTexcoord.xy) * varColor;
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<$VERSION_HEADER$>
|
||||
// Generated on <$_SCRIBE_DATE$>
|
||||
//
|
||||
// particle vertex shader
|
||||
// texture_particle.vert
|
||||
//
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
|
@ -43,15 +43,15 @@ struct ParticleUniforms {
|
|||
vec2 spare;
|
||||
};
|
||||
|
||||
layout(std140) uniform particleBuffer {
|
||||
layout(std140, binding=0) uniform particleBuffer {
|
||||
ParticleUniforms particle;
|
||||
};
|
||||
|
||||
layout(location=0) in vec3 inPosition;
|
||||
layout(location=2) in vec2 inColor; // This is actual Lifetime + Seed
|
||||
|
||||
out vec4 varColor;
|
||||
out vec2 varTexcoord;
|
||||
layout(location=0) out vec4 varColor;
|
||||
layout(location=1) out vec2 varTexcoord;
|
||||
|
||||
float bezierInterpolate(float y1, float y2, float y3, float u) {
|
||||
// https://en.wikipedia.org/wiki/Bezier_curve
|
||||
|
|
|
@ -269,7 +269,9 @@ void Context::create() {
|
|||
#if defined(USE_GLES)
|
||||
_version = 0x0200;
|
||||
#else
|
||||
if (GLAD_GL_VERSION_4_5) {
|
||||
if (gl::disableGl45()) {
|
||||
_version = 0x0401;
|
||||
} else if (GLAD_GL_VERSION_4_5) {
|
||||
_version = 0x0405;
|
||||
} else if (GLAD_GL_VERSION_4_3) {
|
||||
_version = 0x0403;
|
||||
|
|
|
@ -24,6 +24,26 @@ size_t evalGLFormatSwapchainPixelSize(const QSurfaceFormat& format) {
|
|||
return pixelSize;
|
||||
}
|
||||
|
||||
bool gl::disableGl45() {
|
||||
#if defined(USE_GLES)
|
||||
return false;
|
||||
#else
|
||||
static const QString DEBUG_FLAG("HIFI_DISABLE_OPENGL_45");
|
||||
static bool disableOpenGL45 = QProcessEnvironment::systemEnvironment().contains(DEBUG_FLAG);
|
||||
return disableOpenGL45;
|
||||
#endif
|
||||
}
|
||||
|
||||
void gl::getTargetVersion(int& major, int& minor) {
|
||||
#if defined(USE_GLES)
|
||||
major = 3;
|
||||
minor = 2;
|
||||
#else
|
||||
major = 4;
|
||||
minor = disableGl45() ? 1 : 5;
|
||||
#endif
|
||||
}
|
||||
|
||||
const QSurfaceFormat& getDefaultOpenGLSurfaceFormat() {
|
||||
static QSurfaceFormat format;
|
||||
static std::once_flag once;
|
||||
|
@ -40,7 +60,10 @@ const QSurfaceFormat& getDefaultOpenGLSurfaceFormat() {
|
|||
// Qt Quick may need a depth and stencil buffer. Always make sure these are available.
|
||||
format.setDepthBufferSize(DEFAULT_GL_DEPTH_BUFFER_BITS);
|
||||
format.setStencilBufferSize(DEFAULT_GL_STENCIL_BUFFER_BITS);
|
||||
setGLFormatVersion(format);
|
||||
int major, minor;
|
||||
::gl::getTargetVersion(major, minor);
|
||||
format.setMajorVersion(major);
|
||||
format.setMinorVersion(minor);
|
||||
QSurfaceFormat::setDefaultFormat(format);
|
||||
});
|
||||
return format;
|
||||
|
|
|
@ -26,15 +26,6 @@ class QOpenGLDebugMessage;
|
|||
class QSurfaceFormat;
|
||||
class QGLFormat;
|
||||
|
||||
template<class F>
|
||||
// https://bugreports.qt.io/browse/QTBUG-64703 prevents us from using "defined(QT_OPENGL_ES_3_1)"
|
||||
#if defined(USE_GLES)
|
||||
void setGLFormatVersion(F& format, int major = 3, int minor = 2)
|
||||
#else
|
||||
void setGLFormatVersion(F& format, int major = 4, int minor = 5)
|
||||
#endif
|
||||
{ format.setVersion(major, minor); }
|
||||
|
||||
size_t evalGLFormatSwapchainPixelSize(const QSurfaceFormat& format);
|
||||
|
||||
const QSurfaceFormat& getDefaultOpenGLSurfaceFormat();
|
||||
|
@ -50,6 +41,9 @@ namespace gl {
|
|||
|
||||
bool checkGLErrorDebug(const char* name);
|
||||
|
||||
bool disableGl45();
|
||||
|
||||
void getTargetVersion(int& major, int& minor);
|
||||
} // namespace gl
|
||||
|
||||
#define CHECK_GL_ERROR() ::gl::checkGLErrorDebug(__FUNCTION__)
|
||||
|
|
|
@ -13,32 +13,194 @@
|
|||
using namespace gl;
|
||||
|
||||
void Uniform::load(GLuint glprogram, int index) {
|
||||
this->index = index;
|
||||
const GLint NAME_LENGTH = 256;
|
||||
GLchar glname[NAME_LENGTH];
|
||||
GLint length = 0;
|
||||
glGetActiveUniform(glprogram, index, NAME_LENGTH, &length, &size, &type, glname);
|
||||
// Length does NOT include the null terminator
|
||||
// https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGetActiveUniform.xhtml
|
||||
name = std::string(glname, length);
|
||||
location = glGetUniformLocation(glprogram, glname);
|
||||
binding = glGetUniformLocation(glprogram, glname);
|
||||
}
|
||||
|
||||
Uniforms gl::loadUniforms(GLuint glprogram) {
|
||||
bool isTextureType(GLenum type) {
|
||||
switch (type) {
|
||||
#ifndef USE_GLES
|
||||
case GL_SAMPLER_1D:
|
||||
case GL_SAMPLER_1D_ARRAY:
|
||||
case GL_SAMPLER_1D_SHADOW:
|
||||
case GL_SAMPLER_1D_ARRAY_SHADOW:
|
||||
#endif
|
||||
case GL_SAMPLER_2D:
|
||||
case GL_SAMPLER_3D:
|
||||
case GL_SAMPLER_CUBE:
|
||||
case GL_SAMPLER_2D_ARRAY:
|
||||
case GL_SAMPLER_CUBE_MAP_ARRAY:
|
||||
case GL_SAMPLER_2D_SHADOW:
|
||||
case GL_SAMPLER_2D_ARRAY_SHADOW:
|
||||
case GL_SAMPLER_BUFFER:
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Uniforms Uniform::load(GLuint glprogram, const std::function<bool(const Uniform&)>& filter) {
|
||||
Uniforms result;
|
||||
GLint uniformsCount = 0;
|
||||
glGetProgramiv(glprogram, GL_ACTIVE_UNIFORMS, &uniformsCount);
|
||||
|
||||
Uniforms result;
|
||||
result.resize(uniformsCount);
|
||||
result.reserve(uniformsCount);
|
||||
for (int i = 0; i < uniformsCount; i++) {
|
||||
result[i].load(glprogram, i);
|
||||
result.emplace_back(glprogram, i);
|
||||
}
|
||||
result.erase(std::remove_if(result.begin(), result.end(), filter), result.end());
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
Uniforms Uniform::loadTextures(GLuint glprogram) {
|
||||
return load(glprogram, [](const Uniform& uniform) -> bool {
|
||||
if (std::string::npos != uniform.name.find('.')) {
|
||||
return true;
|
||||
}
|
||||
if (std::string::npos != uniform.name.find('[')) {
|
||||
return true;
|
||||
}
|
||||
if (!isTextureType(uniform.type)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
Uniforms Uniform::load(GLuint glprogram) {
|
||||
return load(glprogram, [](const Uniform& uniform) -> bool {
|
||||
if (std::string::npos != uniform.name.find('.')) {
|
||||
return true;
|
||||
}
|
||||
if (std::string::npos != uniform.name.find('[')) {
|
||||
return true;
|
||||
}
|
||||
if (isTextureType(uniform.type)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
Uniforms Uniform::load(GLuint glprogram, const std::vector<GLuint>& indices) {
|
||||
Uniforms result;
|
||||
result.reserve(indices.size());
|
||||
for (const auto& i : indices) {
|
||||
if (i == GL_INVALID_INDEX) {
|
||||
continue;
|
||||
}
|
||||
result.emplace_back(glprogram, i);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
Uniform Uniform::loadByName(GLuint glprogram, const std::string& name) {
|
||||
GLuint index;
|
||||
const char* nameCStr = name.c_str();
|
||||
glGetUniformIndices(glprogram, 1, &nameCStr, &index);
|
||||
Uniform result;
|
||||
if (index != GL_INVALID_INDEX) {
|
||||
result.load(glprogram, index);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
Uniforms Uniform::load(GLuint glprogram, const std::vector<const char*>& cnames) {
|
||||
GLsizei count = static_cast<GLsizei>(cnames.size());
|
||||
if (0 == count) {
|
||||
return {};
|
||||
}
|
||||
std::vector<GLuint> indices;
|
||||
indices.resize(count);
|
||||
glGetUniformIndices(glprogram, count, cnames.data(), indices.data());
|
||||
return load(glprogram, indices);
|
||||
}
|
||||
|
||||
|
||||
template <typename C, typename F>
|
||||
std::vector<const char*> toCNames(const C& container, F lambda) {
|
||||
std::vector<const char*> result;
|
||||
result.reserve(container.size());
|
||||
std::transform(container.begin(), container.end(), std::back_inserter(result), lambda);
|
||||
return result;
|
||||
}
|
||||
|
||||
Uniforms Uniform::load(GLuint glprogram, const std::vector<std::string>& names) {
|
||||
auto cnames = toCNames(names, [](const std::string& name) { return name.c_str(); });
|
||||
return load(glprogram, cnames);
|
||||
}
|
||||
|
||||
void UniformBlock::load(GLuint glprogram, int index) {
|
||||
this->index = index;
|
||||
GLint length = 0;
|
||||
|
||||
// Length DOES include the null terminator
|
||||
// https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGetActiveUniformBlock.xhtml
|
||||
glGetActiveUniformBlockiv(glprogram, index, GL_UNIFORM_BLOCK_NAME_LENGTH, &length);
|
||||
if (length > 1) {
|
||||
std::vector<char> nameBuffer;
|
||||
nameBuffer.resize(length);
|
||||
glGetActiveUniformBlockName(glprogram, index, length, nullptr, nameBuffer.data());
|
||||
name = std::string(nameBuffer.data(), length - 1);
|
||||
}
|
||||
glGetActiveUniformBlockiv(glprogram, index, GL_UNIFORM_BLOCK_BINDING, &binding);
|
||||
glGetActiveUniformBlockiv(glprogram, index, GL_UNIFORM_BLOCK_DATA_SIZE, &size);
|
||||
}
|
||||
|
||||
UniformBlocks UniformBlock::load(GLuint glprogram) {
|
||||
GLint buffersCount = -1;
|
||||
glGetProgramiv(glprogram, GL_ACTIVE_UNIFORM_BLOCKS, &buffersCount);
|
||||
|
||||
// fast exit
|
||||
if (buffersCount <= 0) {
|
||||
return {};
|
||||
}
|
||||
|
||||
UniformBlocks uniformBlocks;
|
||||
for (int i = 0; i < buffersCount; ++i) {
|
||||
uniformBlocks.emplace_back(glprogram, i);
|
||||
}
|
||||
return uniformBlocks;
|
||||
}
|
||||
|
||||
void Input::load(GLuint glprogram, int index) {
|
||||
const GLint NAME_LENGTH = 256;
|
||||
GLchar name[NAME_LENGTH];
|
||||
GLint length = 0;
|
||||
// Length does NOT include the null terminator
|
||||
// https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGetActiveAttrib.xhtml
|
||||
glGetActiveAttrib(glprogram, index, NAME_LENGTH, &length, &size, &type, name);
|
||||
if (length > 0) {
|
||||
this->name = std::string(name, length);
|
||||
}
|
||||
binding = glGetAttribLocation(glprogram, name);
|
||||
}
|
||||
|
||||
Inputs Input::load(GLuint glprogram) {
|
||||
Inputs result;
|
||||
GLint count;
|
||||
glGetProgramiv(glprogram, GL_ACTIVE_ATTRIBUTES, &count);
|
||||
for (int i = 0; i < count; ++i) {
|
||||
result.emplace_back(glprogram, i);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
#ifdef SEPARATE_PROGRAM
|
||||
bool gl::compileShader(GLenum shaderDomain,
|
||||
const std::string& shaderSource,
|
||||
GLuint& shaderObject,
|
||||
GLuint& programObject,
|
||||
std::string& message) {
|
||||
const std::string& shaderSource,
|
||||
GLuint& shaderObject,
|
||||
GLuint& programObject,
|
||||
std::string& message) {
|
||||
return compileShader(shaderDomain, std::vector<std::string>{ shaderSource }, shaderObject, programObject, message);
|
||||
}
|
||||
#else
|
||||
|
@ -49,15 +211,15 @@ bool gl::compileShader(GLenum shaderDomain, const std::string& shaderSource, GLu
|
|||
|
||||
#ifdef SEPARATE_PROGRAM
|
||||
bool gl::compileShader(GLenum shaderDomain,
|
||||
const std::string& shaderSource,
|
||||
GLuint& shaderObject,
|
||||
GLuint& programObject,
|
||||
std::string& message) {
|
||||
const std::string& shaderSource,
|
||||
GLuint& shaderObject,
|
||||
GLuint& programObject,
|
||||
std::string& message) {
|
||||
#else
|
||||
bool gl::compileShader(GLenum shaderDomain,
|
||||
const std::vector<std::string>& shaderSources,
|
||||
GLuint& shaderObject,
|
||||
std::string& message) {
|
||||
const std::vector<std::string>& shaderSources,
|
||||
GLuint& shaderObject,
|
||||
std::string& message) {
|
||||
#endif
|
||||
if (shaderSources.empty()) {
|
||||
qCDebug(glLogging) << "GLShader::compileShader - no GLSL shader source code ? so failed to create";
|
||||
|
@ -85,57 +247,28 @@ bool gl::compileShader(GLenum shaderDomain,
|
|||
GLint compiled = 0;
|
||||
glGetShaderiv(glshader, GL_COMPILE_STATUS, &compiled);
|
||||
|
||||
GLint infoLength = 0;
|
||||
glGetShaderiv(glshader, GL_INFO_LOG_LENGTH, &infoLength);
|
||||
|
||||
if ((infoLength > 0) || !compiled) {
|
||||
char* temp = new char[infoLength];
|
||||
glGetShaderInfoLog(glshader, infoLength, NULL, temp);
|
||||
|
||||
message = std::string(temp);
|
||||
|
||||
// if compilation fails
|
||||
if (!compiled) {
|
||||
// save the source code to a temp file so we can debug easily
|
||||
/*
|
||||
std::ofstream filestream;
|
||||
filestream.open("debugshader.glsl");
|
||||
if (filestream.is_open()) {
|
||||
filestream << srcstr[0];
|
||||
filestream << srcstr[1];
|
||||
filestream.close();
|
||||
getShaderInfoLog(glshader, message);
|
||||
// if compilation fails
|
||||
if (!compiled) {
|
||||
qCCritical(glLogging) << "GLShader::compileShader - failed to compile the gl shader object:";
|
||||
int lineNumber = 0;
|
||||
for (const auto& s : cstrs) {
|
||||
QString str(s);
|
||||
QStringList lines = str.split("\n");
|
||||
for (auto& line : lines) {
|
||||
qCCritical(glLogging).noquote() << QString("%1: %2").arg(lineNumber++, 5, 10, QChar('0')).arg(line);
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
filestream.open("debugshader.glsl.info.txt");
|
||||
if (filestream.is_open()) {
|
||||
filestream << std::string(temp);
|
||||
filestream.close();
|
||||
}
|
||||
*/
|
||||
|
||||
qCCritical(glLogging) << "GLShader::compileShader - failed to compile the gl shader object:";
|
||||
int lineNumber = 0;
|
||||
for (const auto& s : cstrs) {
|
||||
QString str(s);
|
||||
QStringList lines = str.split("\n");
|
||||
for (auto& line : lines) {
|
||||
qCCritical(glLogging).noquote() << QString("%1: %2").arg(lineNumber++, 5, 10, QChar('0')).arg(line);
|
||||
}
|
||||
}
|
||||
qCCritical(glLogging) << "GLShader::compileShader - errors:";
|
||||
qCCritical(glLogging) << temp;
|
||||
|
||||
delete[] temp;
|
||||
glDeleteShader(glshader);
|
||||
return false;
|
||||
}
|
||||
qCCritical(glLogging) << "GLShader::compileShader - errors:";
|
||||
qCCritical(glLogging) << message.c_str();
|
||||
glDeleteShader(glshader);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!message.empty()) {
|
||||
// Compilation success
|
||||
qCWarning(glLogging) << "GLShader::compileShader - Success:";
|
||||
qCWarning(glLogging) << temp;
|
||||
delete[] temp;
|
||||
qCWarning(glLogging) << message.c_str();
|
||||
}
|
||||
|
||||
#ifdef SEPARATE_PROGRAM
|
||||
|
@ -193,7 +326,47 @@ bool gl::compileShader(GLenum shaderDomain,
|
|||
return true;
|
||||
}
|
||||
|
||||
GLuint gl::compileProgram(const std::vector<GLuint>& glshaders, std::string& message, CachedShader& cachedShader) {
|
||||
void gl::getShaderInfoLog(GLuint glshader, std::string& message) {
|
||||
std::string result;
|
||||
GLint infoLength = 0;
|
||||
glGetShaderiv(glshader, GL_INFO_LOG_LENGTH, &infoLength);
|
||||
if (infoLength > 0) {
|
||||
char* temp = new char[infoLength];
|
||||
glGetShaderInfoLog(glshader, infoLength, NULL, temp);
|
||||
message = std::string(temp);
|
||||
delete[] temp;
|
||||
} else {
|
||||
message.clear();
|
||||
}
|
||||
}
|
||||
|
||||
void gl::getProgramInfoLog(GLuint glprogram, std::string& message) {
|
||||
std::string result;
|
||||
GLint infoLength = 0;
|
||||
glGetProgramiv(glprogram, GL_INFO_LOG_LENGTH, &infoLength);
|
||||
if (infoLength > 0) {
|
||||
char* temp = new char[infoLength];
|
||||
glGetProgramInfoLog(glprogram, infoLength, NULL, temp);
|
||||
message = std::string(temp);
|
||||
delete[] temp;
|
||||
} else {
|
||||
message.clear();
|
||||
}
|
||||
}
|
||||
|
||||
void gl::getProgramBinary(GLuint glprogram, CachedShader& cachedShader) {
|
||||
GLint binaryLength = 0;
|
||||
glGetProgramiv(glprogram, GL_PROGRAM_BINARY_LENGTH, &binaryLength);
|
||||
if (binaryLength > 0) {
|
||||
cachedShader.binary.resize(binaryLength);
|
||||
glGetProgramBinary(glprogram, binaryLength, NULL, &cachedShader.format, cachedShader.binary.data());
|
||||
} else {
|
||||
cachedShader.binary.clear();
|
||||
cachedShader.format = 0;
|
||||
}
|
||||
}
|
||||
|
||||
GLuint gl::buildProgram(const std::vector<GLuint>& glshaders) {
|
||||
// A brand new program:
|
||||
GLuint glprogram = glCreateProgram();
|
||||
if (!glprogram) {
|
||||
|
@ -201,80 +374,55 @@ GLuint gl::compileProgram(const std::vector<GLuint>& glshaders, std::string& mes
|
|||
return 0;
|
||||
}
|
||||
|
||||
bool binaryLoaded = false;
|
||||
|
||||
if (glshaders.empty() && cachedShader) {
|
||||
glProgramBinary(glprogram, cachedShader.format, cachedShader.binary.data(), (GLsizei)cachedShader.binary.size());
|
||||
binaryLoaded = true;
|
||||
} else {
|
||||
// glProgramParameteri(glprogram, GL_PROGRAM_, GL_TRUE);
|
||||
// Create the program from the sub shaders
|
||||
for (auto so : glshaders) {
|
||||
glAttachShader(glprogram, so);
|
||||
}
|
||||
|
||||
// Link!
|
||||
glLinkProgram(glprogram);
|
||||
}
|
||||
|
||||
GLint linked = 0;
|
||||
glGetProgramiv(glprogram, GL_LINK_STATUS, &linked);
|
||||
|
||||
GLint infoLength = 0;
|
||||
glGetProgramiv(glprogram, GL_INFO_LOG_LENGTH, &infoLength);
|
||||
|
||||
if ((infoLength > 0) || !linked) {
|
||||
char* temp = new char[infoLength];
|
||||
glGetProgramInfoLog(glprogram, infoLength, NULL, temp);
|
||||
|
||||
message = std::string(temp);
|
||||
|
||||
if (!linked) {
|
||||
/*
|
||||
// save the source code to a temp file so we can debug easily
|
||||
std::ofstream filestream;
|
||||
filestream.open("debugshader.glsl");
|
||||
if (filestream.is_open()) {
|
||||
filestream << shaderSource->source;
|
||||
filestream.close();
|
||||
}
|
||||
*/
|
||||
|
||||
qCDebug(glLogging) << "GLShader::compileProgram - failed to LINK the gl program object :";
|
||||
qCDebug(glLogging) << temp;
|
||||
|
||||
delete[] temp;
|
||||
|
||||
/*
|
||||
filestream.open("debugshader.glsl.info.txt");
|
||||
if (filestream.is_open()) {
|
||||
filestream << std::string(temp);
|
||||
filestream.close();
|
||||
}
|
||||
*/
|
||||
|
||||
glDeleteProgram(glprogram);
|
||||
return 0;
|
||||
} else {
|
||||
qCDebug(glLogging) << "GLShader::compileProgram - success:";
|
||||
qCDebug(glLogging) << temp;
|
||||
delete[] temp;
|
||||
}
|
||||
}
|
||||
|
||||
// If linked get the binaries
|
||||
if (linked && !binaryLoaded) {
|
||||
GLint binaryLength = 0;
|
||||
glGetProgramiv(glprogram, GL_PROGRAM_BINARY_LENGTH, &binaryLength);
|
||||
if (binaryLength > 0) {
|
||||
cachedShader.binary.resize(binaryLength);
|
||||
glGetProgramBinary(glprogram, binaryLength, NULL, &cachedShader.format, cachedShader.binary.data());
|
||||
}
|
||||
// glProgramParameteri(glprogram, GL_PROGRAM_, GL_TRUE);
|
||||
// Create the program from the sub shaders
|
||||
for (auto so : glshaders) {
|
||||
glAttachShader(glprogram, so);
|
||||
}
|
||||
|
||||
return glprogram;
|
||||
}
|
||||
|
||||
|
||||
GLuint gl::buildProgram(const CachedShader& cachedShader) {
|
||||
// A brand new program:
|
||||
GLuint glprogram = glCreateProgram();
|
||||
if (!glprogram) {
|
||||
qCDebug(glLogging) << "GLShader::compileProgram - failed to create the gl program object";
|
||||
return 0;
|
||||
}
|
||||
glProgramBinary(glprogram, cachedShader.format, cachedShader.binary.data(), (GLsizei)cachedShader.binary.size());
|
||||
GLint linked = 0;
|
||||
glGetProgramiv(glprogram, GL_LINK_STATUS, &linked);
|
||||
if (!linked) {
|
||||
glDeleteProgram(glprogram);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return glprogram;
|
||||
}
|
||||
|
||||
|
||||
bool gl::linkProgram(GLuint glprogram, std::string& message) {
|
||||
glLinkProgram(glprogram);
|
||||
|
||||
GLint linked = 0;
|
||||
glGetProgramiv(glprogram, GL_LINK_STATUS, &linked);
|
||||
::gl::getProgramInfoLog(glprogram, message);
|
||||
if (!linked) {
|
||||
qCDebug(glLogging) << "GLShader::compileProgram - failed to LINK the gl program object :";
|
||||
qCDebug(glLogging) << message.c_str();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!message.empty()) {
|
||||
qCDebug(glLogging) << "GLShader::compileProgram - success:";
|
||||
qCDebug(glLogging) << message.c_str();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
const QString& getShaderCacheFile() {
|
||||
static const QString SHADER_CACHE_FOLDER{ "shaders" };
|
||||
static const QString SHADER_CACHE_FILE_NAME{ "cache.json" };
|
||||
|
@ -287,6 +435,7 @@ static const char* SHADER_JSON_SOURCE_KEY = "source";
|
|||
static const char* SHADER_JSON_DATA_KEY = "data";
|
||||
|
||||
void gl::loadShaderCache(ShaderCache& cache) {
|
||||
#if !defined(DISABLE_QML)
|
||||
QString shaderCacheFile = getShaderCacheFile();
|
||||
if (QFileInfo(shaderCacheFile).exists()) {
|
||||
QString json = FileUtils::readFile(shaderCacheFile);
|
||||
|
@ -302,6 +451,7 @@ void gl::loadShaderCache(ShaderCache& cache) {
|
|||
cachedShader.source = programObject[SHADER_JSON_SOURCE_KEY].toString().toStdString();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void gl::saveShaderCache(const ShaderCache& cache) {
|
||||
|
|
|
@ -12,50 +12,114 @@
|
|||
|
||||
#include "Config.h"
|
||||
|
||||
#include <vector>
|
||||
#include <functional>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
|
||||
namespace gl {
|
||||
|
||||
struct Uniform {
|
||||
std::string name;
|
||||
GLint size{ -1 };
|
||||
GLenum type{ GL_FLOAT };
|
||||
GLint location{ -1 };
|
||||
void load(GLuint glprogram, int index);
|
||||
};
|
||||
struct ShaderBinding {
|
||||
int index;
|
||||
std::string name;
|
||||
GLint size{ -1 };
|
||||
GLint binding{ -1 };
|
||||
};
|
||||
|
||||
using Uniforms = std::vector<Uniform>;
|
||||
struct Uniform : public ShaderBinding {
|
||||
Uniform(){};
|
||||
Uniform(GLint program, int index) { load(program, index); };
|
||||
using Vector = std::vector<Uniform>;
|
||||
GLenum type{ GL_FLOAT };
|
||||
|
||||
Uniforms loadUniforms(GLuint glprogram);
|
||||
void load(GLuint glprogram, int index);
|
||||
// Incredibly slow on mac, DO NOT USE
|
||||
static Vector load(GLuint glprogram, const std::function<bool(const Uniform&)>& filter);
|
||||
static Vector loadTextures(GLuint glprogram);
|
||||
static Vector load(GLuint glprogram);
|
||||
static Vector load(GLuint glprogram, const std::vector<GLuint>& indices);
|
||||
static Vector load(GLuint glprogram, const std::vector<const char*>& names);
|
||||
static Vector load(GLuint glprogram, const std::vector<std::string>& names);
|
||||
static Uniform loadByName(GLuint glprogram, const std::string& names);
|
||||
|
||||
struct CachedShader {
|
||||
GLenum format{ 0 };
|
||||
std::string source;
|
||||
std::vector<char> binary;
|
||||
inline operator bool() const {
|
||||
return format != 0 && !binary.empty();
|
||||
template <typename C>
|
||||
static Vector loadByName(GLuint glprogram, const C& names) {
|
||||
if (names.empty()) {
|
||||
return {};
|
||||
}
|
||||
};
|
||||
std::vector<const char*> cnames;
|
||||
cnames.reserve(names.size());
|
||||
for (const auto& name : names) {
|
||||
cnames.push_back(name.c_str());
|
||||
}
|
||||
return load(glprogram, cnames);
|
||||
}
|
||||
};
|
||||
|
||||
using ShaderCache = std::unordered_map<std::string, CachedShader>;
|
||||
using Uniforms = Uniform::Vector;
|
||||
|
||||
std::string getShaderHash(const std::string& shaderSource);
|
||||
void loadShaderCache(ShaderCache& cache);
|
||||
void saveShaderCache(const ShaderCache& cache);
|
||||
struct UniformBlock : public ShaderBinding {
|
||||
UniformBlock(){};
|
||||
UniformBlock(GLint program, int index) { load(program, index); };
|
||||
|
||||
using Vector = std::vector<UniformBlock>;
|
||||
void load(GLuint glprogram, int index);
|
||||
static Vector load(GLuint glprogram);
|
||||
};
|
||||
|
||||
using UniformBlocks = UniformBlock::Vector;
|
||||
|
||||
struct Input : public ShaderBinding {
|
||||
Input(){};
|
||||
Input(GLint program, int index) { load(program, index); };
|
||||
using Vector = std::vector<Uniform>;
|
||||
GLenum type{ GL_FLOAT };
|
||||
|
||||
void load(GLuint glprogram, int index);
|
||||
static Vector load(GLuint glprogram);
|
||||
};
|
||||
|
||||
using Inputs = Input::Vector;
|
||||
|
||||
struct CachedShader {
|
||||
GLenum format{ 0 };
|
||||
std::string source;
|
||||
std::vector<char> binary;
|
||||
inline operator bool() const { return format != 0 && !binary.empty(); }
|
||||
};
|
||||
|
||||
using ShaderCache = std::unordered_map<std::string, CachedShader>;
|
||||
|
||||
std::string getShaderHash(const std::string& shaderSource);
|
||||
void loadShaderCache(ShaderCache& cache);
|
||||
void saveShaderCache(const ShaderCache& cache);
|
||||
|
||||
#ifdef SEPARATE_PROGRAM
|
||||
bool compileShader(GLenum shaderDomain, const std::string& shaderSource, GLuint &shaderObject, GLuint &programObject, std::string& message);
|
||||
bool compileShader(GLenum shaderDomain, const std::vector<std::string>& shaderSources, GLuint &shaderObject, GLuint &programObject, std::string& message);
|
||||
bool compileShader(GLenum shaderDomain,
|
||||
const std::string& shaderSource,
|
||||
GLuint& shaderObject,
|
||||
GLuint& programObject,
|
||||
std::string& message);
|
||||
bool compileShader(GLenum shaderDomain,
|
||||
const std::vector<std::string>& shaderSources,
|
||||
GLuint& shaderObject,
|
||||
GLuint& programObject,
|
||||
std::string& message);
|
||||
#else
|
||||
bool compileShader(GLenum shaderDomain, const std::string& shaderSource, GLuint &shaderObject, std::string& message);
|
||||
bool compileShader(GLenum shaderDomain, const std::vector<std::string>& shaderSources, GLuint &shaderObject, std::string& message);
|
||||
bool compileShader(GLenum shaderDomain, const std::string& shaderSource, GLuint& shaderObject, std::string& message);
|
||||
bool compileShader(GLenum shaderDomain,
|
||||
const std::vector<std::string>& shaderSources,
|
||||
GLuint& shaderObject,
|
||||
std::string& message);
|
||||
#endif
|
||||
|
||||
GLuint compileProgram(const std::vector<GLuint>& glshaders, std::string& message, CachedShader& binary);
|
||||
|
||||
}
|
||||
GLuint buildProgram(const std::vector<GLuint>& glshaders);
|
||||
GLuint buildProgram(const CachedShader& binary);
|
||||
bool linkProgram(GLuint glprogram, std::string& message);
|
||||
void getShaderInfoLog(GLuint glshader, std::string& message);
|
||||
void getProgramInfoLog(GLuint glprogram, std::string& message);
|
||||
void getProgramBinary(GLuint glprogram, CachedShader& cachedShader);
|
||||
} // namespace gl
|
||||
|
||||
#endif
|
||||
|
|
|
@ -100,11 +100,33 @@ GLBackend::CommandCall GLBackend::_commandCalls[Batch::NUM_COMMANDS] =
|
|||
(&::gpu::gl::GLBackend::do_popProfileRange),
|
||||
};
|
||||
|
||||
#define GL_GET_INTEGER(NAME) glGetIntegerv(GL_##NAME, &const_cast<GLint&>(NAME));
|
||||
|
||||
GLint GLBackend::MAX_TEXTURE_IMAGE_UNITS{ 0 };
|
||||
GLint GLBackend::MAX_UNIFORM_BUFFER_BINDINGS{ 0 };
|
||||
GLint GLBackend::MAX_COMBINED_UNIFORM_BLOCKS{ 0 };
|
||||
GLint GLBackend::MAX_COMBINED_TEXTURE_IMAGE_UNITS{ 0 };
|
||||
GLint GLBackend::MAX_UNIFORM_BLOCK_SIZE{ 0 };
|
||||
GLint GLBackend::UNIFORM_BUFFER_OFFSET_ALIGNMENT{ 1 };
|
||||
|
||||
void GLBackend::init() {
|
||||
static std::once_flag once;
|
||||
std::call_once(once, [] {
|
||||
|
||||
|
||||
QString vendor{ (const char*)glGetString(GL_VENDOR) };
|
||||
QString renderer{ (const char*)glGetString(GL_RENDERER) };
|
||||
|
||||
// Textures
|
||||
GL_GET_INTEGER(MAX_TEXTURE_IMAGE_UNITS);
|
||||
GL_GET_INTEGER(MAX_COMBINED_TEXTURE_IMAGE_UNITS);
|
||||
|
||||
// Uniform blocks
|
||||
GL_GET_INTEGER(MAX_UNIFORM_BUFFER_BINDINGS);
|
||||
GL_GET_INTEGER(MAX_COMBINED_UNIFORM_BLOCKS);
|
||||
GL_GET_INTEGER(MAX_UNIFORM_BLOCK_SIZE);
|
||||
GL_GET_INTEGER(UNIFORM_BUFFER_OFFSET_ALIGNMENT);
|
||||
|
||||
qCDebug(gpugllogging) << "GL Version: " << QString((const char*) glGetString(GL_VERSION));
|
||||
qCDebug(gpugllogging) << "GL Shader Language Version: " << QString((const char*) glGetString(GL_SHADING_LANGUAGE_VERSION));
|
||||
qCDebug(gpugllogging) << "GL Vendor: " << vendor;
|
||||
|
@ -115,15 +137,26 @@ void GLBackend::init() {
|
|||
qCDebug(gpugllogging) << "\tcard:" << gpu->getName();
|
||||
qCDebug(gpugllogging) << "\tdriver:" << gpu->getDriver();
|
||||
qCDebug(gpugllogging) << "\tdedicated memory:" << gpu->getMemory() << "MB";
|
||||
qCDebug(gpugllogging) << "Limits:";
|
||||
qCDebug(gpugllogging) << "\tmax textures:" << MAX_TEXTURE_IMAGE_UNITS;
|
||||
qCDebug(gpugllogging) << "\tmax texture binding:" << MAX_COMBINED_TEXTURE_IMAGE_UNITS;
|
||||
qCDebug(gpugllogging) << "\tmax uniforms:" << MAX_UNIFORM_BUFFER_BINDINGS;
|
||||
qCDebug(gpugllogging) << "\tmax uniform binding:" << MAX_COMBINED_UNIFORM_BLOCKS;
|
||||
qCDebug(gpugllogging) << "\tmax uniform size:" << MAX_UNIFORM_BLOCK_SIZE;
|
||||
qCDebug(gpugllogging) << "\tuniform alignment:" << UNIFORM_BUFFER_OFFSET_ALIGNMENT;
|
||||
#if !defined(USE_GLES)
|
||||
qCDebug(gpugllogging, "V-Sync is %s\n", (::gl::getSwapInterval() > 0 ? "ON" : "OFF"));
|
||||
#endif
|
||||
});
|
||||
}
|
||||
|
||||
GLBackend::GLBackend(bool syncCache) {
|
||||
_pipeline._cameraCorrectionBuffer._buffer->flush();
|
||||
initShaderBinaryCache();
|
||||
}
|
||||
|
||||
GLBackend::GLBackend() {
|
||||
_pipeline._cameraCorrectionBuffer._buffer->flush();
|
||||
glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &_uboAlignment);
|
||||
initShaderBinaryCache();
|
||||
}
|
||||
|
||||
|
@ -386,17 +419,11 @@ void GLBackend::do_popProfileRange(const Batch& batch, size_t paramOffset) {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
// TODO: As long as we have gl calls explicitely issued from interface
|
||||
// code, we need to be able to record and batch these calls. THe long
|
||||
// term strategy is to get rid of any GL calls in favor of the HIFI GPU API
|
||||
|
||||
// As long as we don;t use several versions of shaders we can avoid this more complex code path
|
||||
#ifdef GPU_STEREO_CAMERA_BUFFER
|
||||
#define GET_UNIFORM_LOCATION(shaderUniformLoc) ((_pipeline._programShader) ? _pipeline._programShader->getUniformLocation(shaderUniformLoc, (GLShader::Version) isStereo()) : -1)
|
||||
#else
|
||||
#define GET_UNIFORM_LOCATION(shaderUniformLoc) shaderUniformLoc
|
||||
#endif
|
||||
|
||||
void GLBackend::do_glUniform1i(const Batch& batch, size_t paramOffset) {
|
||||
if (_pipeline._program == 0) {
|
||||
// We should call updatePipeline() to bind the program but we are not doing that
|
||||
|
@ -405,8 +432,9 @@ void GLBackend::do_glUniform1i(const Batch& batch, size_t paramOffset) {
|
|||
}
|
||||
updatePipeline();
|
||||
|
||||
GLint location = getRealUniformLocation(batch._params[paramOffset + 1]._int);
|
||||
glUniform1i(
|
||||
GET_UNIFORM_LOCATION(batch._params[paramOffset + 1]._int),
|
||||
location,
|
||||
batch._params[paramOffset + 0]._int);
|
||||
(void)CHECK_GL_ERROR();
|
||||
}
|
||||
|
@ -419,8 +447,9 @@ void GLBackend::do_glUniform1f(const Batch& batch, size_t paramOffset) {
|
|||
}
|
||||
updatePipeline();
|
||||
|
||||
GLint location = getRealUniformLocation(batch._params[paramOffset + 1]._int);
|
||||
glUniform1f(
|
||||
GET_UNIFORM_LOCATION(batch._params[paramOffset + 1]._int),
|
||||
location,
|
||||
batch._params[paramOffset + 0]._float);
|
||||
(void)CHECK_GL_ERROR();
|
||||
}
|
||||
|
@ -432,8 +461,9 @@ void GLBackend::do_glUniform2f(const Batch& batch, size_t paramOffset) {
|
|||
return;
|
||||
}
|
||||
updatePipeline();
|
||||
GLint location = getRealUniformLocation(batch._params[paramOffset + 2]._int);
|
||||
glUniform2f(
|
||||
GET_UNIFORM_LOCATION(batch._params[paramOffset + 2]._int),
|
||||
location,
|
||||
batch._params[paramOffset + 1]._float,
|
||||
batch._params[paramOffset + 0]._float);
|
||||
(void)CHECK_GL_ERROR();
|
||||
|
@ -446,8 +476,9 @@ void GLBackend::do_glUniform3f(const Batch& batch, size_t paramOffset) {
|
|||
return;
|
||||
}
|
||||
updatePipeline();
|
||||
GLint location = getRealUniformLocation(batch._params[paramOffset + 3]._int);
|
||||
glUniform3f(
|
||||
GET_UNIFORM_LOCATION(batch._params[paramOffset + 3]._int),
|
||||
location,
|
||||
batch._params[paramOffset + 2]._float,
|
||||
batch._params[paramOffset + 1]._float,
|
||||
batch._params[paramOffset + 0]._float);
|
||||
|
@ -461,8 +492,9 @@ void GLBackend::do_glUniform4f(const Batch& batch, size_t paramOffset) {
|
|||
return;
|
||||
}
|
||||
updatePipeline();
|
||||
GLint location = getRealUniformLocation(batch._params[paramOffset + 4]._int);
|
||||
glUniform4f(
|
||||
GET_UNIFORM_LOCATION(batch._params[paramOffset + 4]._int),
|
||||
location,
|
||||
batch._params[paramOffset + 3]._float,
|
||||
batch._params[paramOffset + 2]._float,
|
||||
batch._params[paramOffset + 1]._float,
|
||||
|
@ -477,8 +509,9 @@ void GLBackend::do_glUniform3fv(const Batch& batch, size_t paramOffset) {
|
|||
return;
|
||||
}
|
||||
updatePipeline();
|
||||
GLint location = getRealUniformLocation(batch._params[paramOffset + 2]._int);
|
||||
glUniform3fv(
|
||||
GET_UNIFORM_LOCATION(batch._params[paramOffset + 2]._int),
|
||||
location,
|
||||
batch._params[paramOffset + 1]._uint,
|
||||
(const GLfloat*)batch.readData(batch._params[paramOffset + 0]._uint));
|
||||
|
||||
|
@ -493,7 +526,7 @@ void GLBackend::do_glUniform4fv(const Batch& batch, size_t paramOffset) {
|
|||
}
|
||||
updatePipeline();
|
||||
|
||||
GLint location = GET_UNIFORM_LOCATION(batch._params[paramOffset + 2]._int);
|
||||
GLint location = getRealUniformLocation(batch._params[paramOffset + 2]._int);
|
||||
GLsizei count = batch._params[paramOffset + 1]._uint;
|
||||
const GLfloat* value = (const GLfloat*)batch.readData(batch._params[paramOffset + 0]._uint);
|
||||
glUniform4fv(location, count, value);
|
||||
|
@ -508,8 +541,9 @@ void GLBackend::do_glUniform4iv(const Batch& batch, size_t paramOffset) {
|
|||
return;
|
||||
}
|
||||
updatePipeline();
|
||||
GLint location = getRealUniformLocation(batch._params[paramOffset + 2]._int);
|
||||
glUniform4iv(
|
||||
GET_UNIFORM_LOCATION(batch._params[paramOffset + 2]._int),
|
||||
location,
|
||||
batch._params[paramOffset + 1]._uint,
|
||||
(const GLint*)batch.readData(batch._params[paramOffset + 0]._uint));
|
||||
|
||||
|
@ -524,8 +558,9 @@ void GLBackend::do_glUniformMatrix3fv(const Batch& batch, size_t paramOffset) {
|
|||
}
|
||||
updatePipeline();
|
||||
|
||||
GLint location = getRealUniformLocation(batch._params[paramOffset + 3]._int);
|
||||
glUniformMatrix3fv(
|
||||
GET_UNIFORM_LOCATION(batch._params[paramOffset + 3]._int),
|
||||
location,
|
||||
batch._params[paramOffset + 2]._uint,
|
||||
batch._params[paramOffset + 1]._uint,
|
||||
(const GLfloat*)batch.readData(batch._params[paramOffset + 0]._uint));
|
||||
|
@ -540,8 +575,9 @@ void GLBackend::do_glUniformMatrix4fv(const Batch& batch, size_t paramOffset) {
|
|||
}
|
||||
updatePipeline();
|
||||
|
||||
GLint location = getRealUniformLocation(batch._params[paramOffset + 3]._int);
|
||||
glUniformMatrix4fv(
|
||||
GET_UNIFORM_LOCATION(batch._params[paramOffset + 3]._int),
|
||||
location,
|
||||
batch._params[paramOffset + 2]._uint,
|
||||
batch._params[paramOffset + 1]._uint,
|
||||
(const GLfloat*)batch.readData(batch._params[paramOffset + 0]._uint));
|
||||
|
|
|
@ -68,7 +68,29 @@ protected:
|
|||
explicit GLBackend(bool syncCache);
|
||||
GLBackend();
|
||||
public:
|
||||
static bool makeProgram(Shader& shader, const Shader::BindingSet& slotBindings, const Shader::CompilationHandler& handler);
|
||||
|
||||
#if defined(USE_GLES)
|
||||
// https://www.khronos.org/registry/OpenGL-Refpages/es3/html/glGet.xhtml
|
||||
static const GLint MIN_REQUIRED_TEXTURE_IMAGE_UNITS = 16;
|
||||
static const GLint MIN_REQUIRED_COMBINED_UNIFORM_BLOCKS = 60;
|
||||
static const GLint MIN_REQUIRED_COMBINED_TEXTURE_IMAGE_UNITS = 48;
|
||||
static const GLint MIN_REQUIRED_UNIFORM_BUFFER_BINDINGS = 72;
|
||||
static const GLint MIN_REQUIRED_UNIFORM_LOCATIONS = 1024;
|
||||
#else
|
||||
// https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGet.xhtml
|
||||
static const GLint MIN_REQUIRED_TEXTURE_IMAGE_UNITS = 16;
|
||||
static const GLint MIN_REQUIRED_COMBINED_UNIFORM_BLOCKS = 70;
|
||||
static const GLint MIN_REQUIRED_COMBINED_TEXTURE_IMAGE_UNITS = 48;
|
||||
static const GLint MIN_REQUIRED_UNIFORM_BUFFER_BINDINGS = 36;
|
||||
static const GLint MIN_REQUIRED_UNIFORM_LOCATIONS = 1024;
|
||||
#endif
|
||||
|
||||
static GLint MAX_TEXTURE_IMAGE_UNITS;
|
||||
static GLint MAX_UNIFORM_BUFFER_BINDINGS;
|
||||
static GLint MAX_COMBINED_UNIFORM_BLOCKS;
|
||||
static GLint MAX_COMBINED_TEXTURE_IMAGE_UNITS;
|
||||
static GLint MAX_UNIFORM_BLOCK_SIZE;
|
||||
static GLint UNIFORM_BUFFER_OFFSET_ALIGNMENT;
|
||||
|
||||
virtual ~GLBackend();
|
||||
|
||||
|
@ -107,7 +129,6 @@ public:
|
|||
|
||||
// Texture Tables offers 2 dedicated slot (taken from the ubo slots)
|
||||
static const int MAX_NUM_RESOURCE_TABLE_TEXTURES = 2;
|
||||
static const int RESOURCE_TABLE_TEXTURE_SLOT_OFFSET = TRANSFORM_CAMERA_SLOT + 1;
|
||||
size_t getMaxNumResourceTextureTables() const { return MAX_NUM_RESOURCE_TABLE_TEXTURES; }
|
||||
|
||||
|
||||
|
@ -238,6 +259,7 @@ public:
|
|||
bool isTextureManagementSparseEnabled() const override { return (_textureManagement._sparseCapable && Texture::getEnableSparseTextures()); }
|
||||
|
||||
protected:
|
||||
virtual GLint getRealUniformLocation(GLint location) const;
|
||||
|
||||
void recycle() const override;
|
||||
|
||||
|
@ -247,7 +269,6 @@ protected:
|
|||
|
||||
static const size_t INVALID_OFFSET = (size_t)-1;
|
||||
bool _inRenderTransferPass { false };
|
||||
int32_t _uboAlignment { 0 };
|
||||
int _currentDraw { -1 };
|
||||
|
||||
std::list<std::string> profileRanges;
|
||||
|
@ -394,10 +415,24 @@ protected:
|
|||
virtual void transferTransformState(const Batch& batch) const = 0;
|
||||
|
||||
struct UniformStageState {
|
||||
std::array<BufferPointer, MAX_NUM_UNIFORM_BUFFERS> _buffers;
|
||||
//Buffers _buffers { };
|
||||
struct BufferState {
|
||||
BufferPointer buffer;
|
||||
GLintptr offset{ 0 };
|
||||
GLsizeiptr size{ 0 };
|
||||
BufferState(const BufferPointer& buffer = nullptr, GLintptr offset = 0, GLsizeiptr size = 0);
|
||||
bool operator ==(BufferState& other) const {
|
||||
return offset == other.offset && size == other.size && buffer == other.buffer;
|
||||
}
|
||||
};
|
||||
|
||||
// MAX_NUM_UNIFORM_BUFFERS-1 is the max uniform index BATCHES are allowed to set, but
|
||||
// MIN_REQUIRED_UNIFORM_BUFFER_BINDINGS is used here because the backend sets some
|
||||
// internal UBOs for things like camera correction
|
||||
std::array<BufferState, MIN_REQUIRED_UNIFORM_BUFFER_BINDINGS> _buffers;
|
||||
} _uniform;
|
||||
|
||||
// Helper function that provides common code
|
||||
void bindUniformBuffer(uint32_t slot, const BufferPointer& buffer, GLintptr offset = 0, GLsizeiptr size = 0);
|
||||
void releaseUniformBuffer(uint32_t slot);
|
||||
void resetUniformStage();
|
||||
|
||||
|
@ -410,6 +445,7 @@ protected:
|
|||
// do_setResourceTextureTable (in non-bindless mode)
|
||||
void bindResourceTexture(uint32_t slot, const TexturePointer& texture);
|
||||
|
||||
|
||||
// update resource cache and do the gl unbind call with the current gpu::Texture cached at slot s
|
||||
void releaseResourceTexture(uint32_t slot);
|
||||
|
||||
|
@ -436,7 +472,7 @@ protected:
|
|||
PipelinePointer _pipeline;
|
||||
|
||||
GLuint _program { 0 };
|
||||
GLint _cameraCorrectionLocation { -1 };
|
||||
bool _cameraCorrection { false };
|
||||
GLShader* _programShader { nullptr };
|
||||
bool _invalidProgram { false };
|
||||
|
||||
|
@ -457,6 +493,7 @@ protected:
|
|||
} _pipeline;
|
||||
|
||||
// Backend dependant compilation of the shader
|
||||
virtual void postLinkProgram(ShaderObject& programObject, const Shader& program) const;
|
||||
virtual GLShader* compileBackendProgram(const Shader& program, const Shader::CompilationHandler& handler);
|
||||
virtual GLShader* compileBackendShader(const Shader& shader, const Shader::CompilationHandler& handler);
|
||||
virtual std::string getBackendShaderHeader() const = 0;
|
||||
|
@ -467,7 +504,6 @@ protected:
|
|||
// The program string returned can be used as a key for a cache of shader binaries
|
||||
// The shader strings can be reliably sent to the low level `compileShader` functions
|
||||
virtual std::string getShaderSource(const Shader& shader, int version) final;
|
||||
virtual void makeProgramBindings(ShaderObject& shaderObject);
|
||||
class ElementResource {
|
||||
public:
|
||||
gpu::Element _element;
|
||||
|
@ -475,15 +511,6 @@ protected:
|
|||
ElementResource(Element&& elem, uint16 resource) : _element(elem), _resource(resource) {}
|
||||
};
|
||||
ElementResource getFormatFromGLUniform(GLenum gltype);
|
||||
static const GLint UNUSED_SLOT {-1};
|
||||
static bool isUnusedSlot(GLint binding) { return (binding == UNUSED_SLOT); }
|
||||
virtual int makeUniformSlots(const ShaderObject& program, const Shader::BindingSet& slotBindings,
|
||||
Shader::SlotSet& uniforms, Shader::SlotSet& textures, Shader::SlotSet& samplers);
|
||||
virtual int makeUniformBlockSlots(const ShaderObject& program, const Shader::BindingSet& slotBindings, Shader::SlotSet& buffers);
|
||||
virtual int makeResourceBufferSlots(const ShaderObject& program, const Shader::BindingSet& slotBindings, Shader::SlotSet& resourceBuffers) = 0;
|
||||
virtual int makeInputSlots(const ShaderObject& program, const Shader::BindingSet& slotBindings, Shader::SlotSet& inputs);
|
||||
virtual int makeOutputSlots(const ShaderObject& program, const Shader::BindingSet& slotBindings, Shader::SlotSet& outputs);
|
||||
|
||||
|
||||
// Synchronize the state cache of this Backend with the actual real state of the GL Context
|
||||
void syncOutputStateCache();
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
//
|
||||
#include "GLBackend.h"
|
||||
#include <gpu/TextureTable.h>
|
||||
#include <gpu/ShaderConstants.h>
|
||||
|
||||
#include "GLShared.h"
|
||||
#include "GLPipeline.h"
|
||||
|
@ -36,7 +37,7 @@ void GLBackend::do_setPipeline(const Batch& batch, size_t paramOffset) {
|
|||
_pipeline._pipeline.reset();
|
||||
|
||||
_pipeline._program = 0;
|
||||
_pipeline._cameraCorrectionLocation = -1;
|
||||
_pipeline._cameraCorrection = false;
|
||||
_pipeline._programShader = nullptr;
|
||||
_pipeline._invalidProgram = true;
|
||||
|
||||
|
@ -62,7 +63,7 @@ void GLBackend::do_setPipeline(const Batch& batch, size_t paramOffset) {
|
|||
_pipeline._program = glprogram;
|
||||
_pipeline._programShader = pipelineObject->_program;
|
||||
_pipeline._invalidProgram = true;
|
||||
_pipeline._cameraCorrectionLocation = pipelineObject->_cameraCorrection;
|
||||
_pipeline._cameraCorrection = pipelineObject->_cameraCorrection;
|
||||
}
|
||||
|
||||
// Now for the state
|
||||
|
@ -78,16 +79,13 @@ void GLBackend::do_setPipeline(const Batch& batch, size_t paramOffset) {
|
|||
// THis should be done on Pipeline::update...
|
||||
if (_pipeline._invalidProgram) {
|
||||
glUseProgram(_pipeline._program);
|
||||
if (_pipeline._cameraCorrectionLocation != -1) {
|
||||
gl::GLBuffer* cameraCorrectionBuffer = nullptr;
|
||||
if (_transform._viewCorrectionEnabled) {
|
||||
cameraCorrectionBuffer = syncGPUObject(*_pipeline._cameraCorrectionBuffer._buffer);
|
||||
} else {
|
||||
cameraCorrectionBuffer = syncGPUObject(*_pipeline._cameraCorrectionBufferIdentity._buffer);
|
||||
}
|
||||
if (_pipeline._cameraCorrection) {
|
||||
// Invalidate uniform buffer cache slot
|
||||
_uniform._buffers[_pipeline._cameraCorrectionLocation].reset();
|
||||
glBindBufferRange(GL_UNIFORM_BUFFER, _pipeline._cameraCorrectionLocation, cameraCorrectionBuffer->_id, 0, sizeof(CameraCorrection));
|
||||
_uniform._buffers[gpu::slot::buffer::CameraCorrection] = {};
|
||||
auto& cameraCorrectionBuffer = _transform._viewCorrectionEnabled ?
|
||||
_pipeline._cameraCorrectionBuffer._buffer :
|
||||
_pipeline._cameraCorrectionBufferIdentity._buffer;
|
||||
bindUniformBuffer(gpu::slot::buffer::CameraCorrection, cameraCorrectionBuffer, 0, sizeof(CameraCorrection));
|
||||
}
|
||||
(void)CHECK_GL_ERROR();
|
||||
_pipeline._invalidProgram = false;
|
||||
|
@ -138,15 +136,18 @@ void GLBackend::resetPipelineStage() {
|
|||
glUseProgram(0);
|
||||
}
|
||||
|
||||
GLBackend::UniformStageState::BufferState::BufferState(const BufferPointer& buffer, GLintptr offset, GLsizeiptr size)
|
||||
: buffer(buffer), offset(offset), size(size) {}
|
||||
|
||||
void GLBackend::releaseUniformBuffer(uint32_t slot) {
|
||||
auto& buf = _uniform._buffers[slot];
|
||||
if (buf) {
|
||||
auto* object = Backend::getGPUObject<GLBuffer>(*buf);
|
||||
if (buf.buffer) {
|
||||
auto* object = Backend::getGPUObject<GLBuffer>(*buf.buffer);
|
||||
if (object) {
|
||||
glBindBufferBase(GL_UNIFORM_BUFFER, slot, 0); // RELEASE
|
||||
(void)CHECK_GL_ERROR();
|
||||
}
|
||||
buf.reset();
|
||||
buf = UniformStageState::BufferState();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -156,6 +157,33 @@ void GLBackend::resetUniformStage() {
|
|||
}
|
||||
}
|
||||
|
||||
void GLBackend::bindUniformBuffer(uint32_t slot, const BufferPointer& buffer, GLintptr offset, GLsizeiptr size) {
|
||||
if (!buffer) {
|
||||
releaseUniformBuffer(slot);
|
||||
return;
|
||||
}
|
||||
|
||||
UniformStageState::BufferState bufferState{ buffer, offset, size };
|
||||
|
||||
// check cache before thinking
|
||||
if (_uniform._buffers[slot] == bufferState) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Sync BufferObject
|
||||
auto* object = syncGPUObject(*bufferState.buffer);
|
||||
if (object) {
|
||||
glBindBufferRange(GL_UNIFORM_BUFFER, slot, object->_buffer, bufferState.offset, bufferState.size);
|
||||
|
||||
_uniform._buffers[slot] = bufferState;
|
||||
(void)CHECK_GL_ERROR();
|
||||
} else {
|
||||
releaseUniformBuffer(slot);
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void GLBackend::do_setUniformBuffer(const Batch& batch, size_t paramOffset) {
|
||||
GLuint slot = batch._params[paramOffset + 3]._uint;
|
||||
if (slot > (GLuint)MAX_NUM_UNIFORM_BUFFERS) {
|
||||
|
@ -163,31 +191,12 @@ void GLBackend::do_setUniformBuffer(const Batch& batch, size_t paramOffset) {
|
|||
<< " which doesn't exist. MaxNumUniformBuffers = " << getMaxNumUniformBuffers();
|
||||
return;
|
||||
}
|
||||
|
||||
BufferPointer uniformBuffer = batch._buffers.get(batch._params[paramOffset + 2]._uint);
|
||||
GLintptr rangeStart = batch._params[paramOffset + 1]._uint;
|
||||
GLsizeiptr rangeSize = batch._params[paramOffset + 0]._uint;
|
||||
|
||||
if (!uniformBuffer) {
|
||||
releaseUniformBuffer(slot);
|
||||
return;
|
||||
}
|
||||
|
||||
// check cache before thinking
|
||||
if (_uniform._buffers[slot] == uniformBuffer) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Sync BufferObject
|
||||
auto* object = syncGPUObject(*uniformBuffer);
|
||||
if (object) {
|
||||
glBindBufferRange(GL_UNIFORM_BUFFER, slot, object->_buffer, rangeStart, rangeSize);
|
||||
|
||||
_uniform._buffers[slot] = uniformBuffer;
|
||||
(void)CHECK_GL_ERROR();
|
||||
} else {
|
||||
releaseUniformBuffer(slot);
|
||||
return;
|
||||
}
|
||||
bindUniformBuffer(slot, uniformBuffer, rangeStart, rangeSize);
|
||||
}
|
||||
|
||||
void GLBackend::releaseResourceTexture(uint32_t slot) {
|
||||
|
|
|
@ -13,7 +13,6 @@ using namespace gpu;
|
|||
using namespace gpu::gl;
|
||||
using CachedShader = ::gl::CachedShader;
|
||||
|
||||
|
||||
// Shader domain
|
||||
static const size_t NUM_SHADER_DOMAINS = 3;
|
||||
static_assert(Shader::Type::NUM_DOMAINS == NUM_SHADER_DOMAINS, "GL shader domains must equal defined GPU shader domains");
|
||||
|
@ -178,24 +177,22 @@ GLShader* GLBackend::compileBackendProgram(const Shader& program, const Shader::
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
GLuint glprogram = 0;
|
||||
|
||||
// If we have a cached binary program, try to load it instead of compiling the individual shaders
|
||||
if (cachedBinary) {
|
||||
glprogram = ::gl::compileProgram({}, compilationLogs[version].message, cachedBinary);
|
||||
glprogram = ::gl::buildProgram(cachedBinary);
|
||||
if (0 != glprogram) {
|
||||
++gpuBinaryShadersLoaded;
|
||||
}
|
||||
}
|
||||
|
||||
// If we have no program, then either no cached binary, or the binary failed to load (perhaps a GPU driver update invalidated the cache)
|
||||
if (0 == glprogram) {
|
||||
cachedBinary = CachedShader();
|
||||
{
|
||||
} else {
|
||||
cachedBinary = CachedShader();
|
||||
std::unique_lock<std::mutex> shaderCacheLock{ _shaderBinaryCache._mutex };
|
||||
_shaderBinaryCache._binaries.erase(hash);
|
||||
}
|
||||
}
|
||||
|
||||
// If we have no program, then either no cached binary, or the binary failed to load
|
||||
// (perhaps a GPU driver update invalidated the cache)
|
||||
if (0 == glprogram) {
|
||||
// Let's go through every shaders and make sure they are ready to go
|
||||
std::vector<GLuint> shaderGLObjects;
|
||||
shaderGLObjects.reserve(program.getShaders().size());
|
||||
|
@ -212,8 +209,16 @@ GLShader* GLBackend::compileBackendProgram(const Shader& program, const Shader::
|
|||
}
|
||||
}
|
||||
|
||||
glprogram = ::gl::compileProgram(shaderGLObjects, compilationLogs[version].message, cachedBinary);
|
||||
if (cachedBinary) {
|
||||
glprogram = ::gl::buildProgram(shaderGLObjects);
|
||||
|
||||
if (!::gl::linkProgram(glprogram, compilationLogs[version].message)) {
|
||||
glDeleteProgram(glprogram);
|
||||
glprogram = 0;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!cachedBinary) {
|
||||
::gl::getProgramBinary(glprogram, cachedBinary);
|
||||
cachedBinary.source = programSource;
|
||||
std::unique_lock<std::mutex> shaderCacheLock{ _shaderBinaryCache._mutex };
|
||||
_shaderBinaryCache._binaries[hash] = cachedBinary;
|
||||
|
@ -228,7 +233,7 @@ GLShader* GLBackend::compileBackendProgram(const Shader& program, const Shader::
|
|||
|
||||
compilationLogs[version].compiled = true;
|
||||
programObject.glprogram = glprogram;
|
||||
makeProgramBindings(programObject);
|
||||
postLinkProgram(programObject, program);
|
||||
}
|
||||
// Compilation feedback
|
||||
program.setCompilationLogs(compilationLogs);
|
||||
|
@ -236,10 +241,45 @@ GLShader* GLBackend::compileBackendProgram(const Shader& program, const Shader::
|
|||
// So far so good, the program versions have all been created successfully
|
||||
GLShader* object = new GLShader(this->shared_from_this());
|
||||
object->_shaderObjects = programObjects;
|
||||
|
||||
return object;
|
||||
}
|
||||
|
||||
static const GLint INVALID_UNIFORM_INDEX = -1;
|
||||
|
||||
GLint GLBackend::getRealUniformLocation(GLint location) const {
|
||||
auto& shader = _pipeline._programShader->_shaderObjects[(GLShader::Version)isStereo()];
|
||||
auto itr = shader.uniformRemap.find(location);
|
||||
if (itr == shader.uniformRemap.end()) {
|
||||
// This shouldn't happen, because we use reflection to determine all the possible
|
||||
// uniforms. If someone is requesting a uniform that isn't in the remapping structure
|
||||
// that's a bug from the calling code, because it means that location wasn't in the
|
||||
// reflection
|
||||
qWarning() << "Unexpected location requested for shader";
|
||||
return INVALID_UNIFORM_INDEX;
|
||||
}
|
||||
return itr->second;
|
||||
}
|
||||
|
||||
void GLBackend::postLinkProgram(ShaderObject& shaderObject, const Shader& program) const {
|
||||
const auto& glprogram = shaderObject.glprogram;
|
||||
const auto& expectedUniforms = program.getUniforms();
|
||||
const auto expectedLocationsByName = expectedUniforms.getLocationsByName();
|
||||
const auto uniforms = ::gl::Uniform::load(glprogram, expectedUniforms.getNames());
|
||||
auto& uniformRemap = shaderObject.uniformRemap;
|
||||
|
||||
// Pre-initialize all the uniforms with an invalid location
|
||||
for (const auto& entry : expectedLocationsByName) {
|
||||
uniformRemap[entry.second] = INVALID_UNIFORM_INDEX;
|
||||
}
|
||||
|
||||
// Now load up all the actual found uniform location
|
||||
for (const auto& uniform : uniforms) {
|
||||
const auto& name = uniform.name;
|
||||
const auto& expectedLocation = expectedLocationsByName.at(name);
|
||||
const auto& location = uniform.binding;
|
||||
uniformRemap[expectedLocation] = location;
|
||||
}
|
||||
}
|
||||
|
||||
GLBackend::ElementResource GLBackend::getFormatFromGLUniform(GLenum gltype) {
|
||||
switch (gltype) {
|
||||
|
@ -405,197 +445,8 @@ GLBackend::ElementResource GLBackend::getFormatFromGLUniform(GLenum gltype) {
|
|||
//{GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE uimage2DMS},
|
||||
//{GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY uimage2DMSArray},
|
||||
//{GL_UNSIGNED_INT_ATOMIC_COUNTER atomic_uint}
|
||||
|
||||
|
||||
};
|
||||
|
||||
int GLBackend::makeUniformSlots(const ShaderObject& shaderProgram, const Shader::BindingSet& slotBindings,
|
||||
Shader::SlotSet& uniforms, Shader::SlotSet& textures, Shader::SlotSet& samplers) {
|
||||
auto& glprogram = shaderProgram.glprogram;
|
||||
|
||||
for (const auto& uniform : shaderProgram.uniforms) {
|
||||
const auto& type = uniform.type;
|
||||
const auto& location = uniform.location;
|
||||
const auto& size = uniform.size;
|
||||
const auto& name = uniform.name;
|
||||
const GLint INVALID_UNIFORM_LOCATION = -1;
|
||||
|
||||
// Try to make sense of the gltype
|
||||
auto elementResource = getFormatFromGLUniform(type);
|
||||
|
||||
// The uniform as a standard var type
|
||||
if (location != INVALID_UNIFORM_LOCATION) {
|
||||
auto sname = uniform.name;
|
||||
// Let's make sure the name doesn't contains an array element
|
||||
auto foundBracket = sname.find_first_of('[');
|
||||
if (foundBracket != std::string::npos) {
|
||||
// std::string arrayname = sname.substr(0, foundBracket);
|
||||
|
||||
if (sname[foundBracket + 1] == '0') {
|
||||
sname = sname.substr(0, foundBracket);
|
||||
} else {
|
||||
// skip this uniform since it's not the first element of an array
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (elementResource._resource == Resource::BUFFER) {
|
||||
uniforms.insert(Shader::Slot(sname, location, elementResource._element, elementResource._resource));
|
||||
} else {
|
||||
// For texture/Sampler, the location is the actual binding value
|
||||
GLint binding = -1;
|
||||
glGetUniformiv(glprogram, location, &binding);
|
||||
|
||||
auto requestedBinding = slotBindings.find(std::string(sname));
|
||||
if (requestedBinding != slotBindings.end()) {
|
||||
if (binding != (*requestedBinding)._location) {
|
||||
binding = (*requestedBinding)._location;
|
||||
for (auto i = 0; i < size; i++) {
|
||||
// If we are working with an array of textures, reserve for each elemet
|
||||
glProgramUniform1i(glprogram, location+i, binding+i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
textures.insert(Shader::Slot(name, binding, elementResource._element, elementResource._resource));
|
||||
samplers.insert(Shader::Slot(name, binding, elementResource._element, elementResource._resource));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return static_cast<uint32_t>(shaderProgram.uniforms.size());
|
||||
}
|
||||
|
||||
int GLBackend::makeUniformBlockSlots(const ShaderObject& shaderProgram, const Shader::BindingSet& slotBindings, Shader::SlotSet& buffers) {
|
||||
const auto& glprogram = shaderProgram.glprogram;
|
||||
GLint buffersCount = 0;
|
||||
|
||||
glGetProgramiv(glprogram, GL_ACTIVE_UNIFORM_BLOCKS, &buffersCount);
|
||||
|
||||
// fast exit
|
||||
if (buffersCount == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
GLint maxNumUniformBufferSlots = 0;
|
||||
glGetIntegerv(GL_MAX_UNIFORM_BUFFER_BINDINGS, &maxNumUniformBufferSlots);
|
||||
std::vector<GLint> uniformBufferSlotMap(maxNumUniformBufferSlots, -1);
|
||||
|
||||
struct UniformBlockInfo {
|
||||
using Vector = std::vector<UniformBlockInfo>;
|
||||
const GLuint index{ 0 };
|
||||
const std::string name;
|
||||
GLint binding{ -1 };
|
||||
GLint size{ 0 };
|
||||
|
||||
static std::string getName(GLuint glprogram, GLuint i) {
|
||||
static const GLint NAME_LENGTH = 256;
|
||||
GLint length = 0;
|
||||
GLchar nameBuffer[NAME_LENGTH];
|
||||
glGetActiveUniformBlockiv(glprogram, i, GL_UNIFORM_BLOCK_NAME_LENGTH, &length);
|
||||
glGetActiveUniformBlockName(glprogram, i, NAME_LENGTH, &length, nameBuffer);
|
||||
return std::string(nameBuffer);
|
||||
}
|
||||
|
||||
UniformBlockInfo(GLuint glprogram, GLuint i) : index(i), name(getName(glprogram, i)) {
|
||||
glGetActiveUniformBlockiv(glprogram, index, GL_UNIFORM_BLOCK_BINDING, &binding);
|
||||
glGetActiveUniformBlockiv(glprogram, index, GL_UNIFORM_BLOCK_DATA_SIZE, &size);
|
||||
}
|
||||
};
|
||||
|
||||
UniformBlockInfo::Vector uniformBlocks;
|
||||
uniformBlocks.reserve(buffersCount);
|
||||
for (int i = 0; i < buffersCount; i++) {
|
||||
uniformBlocks.push_back(UniformBlockInfo(glprogram, i));
|
||||
}
|
||||
|
||||
for (auto& info : uniformBlocks) {
|
||||
auto requestedBinding = slotBindings.find(info.name);
|
||||
if (requestedBinding != slotBindings.end()) {
|
||||
info.binding = (*requestedBinding)._location;
|
||||
glUniformBlockBinding(glprogram, info.index, info.binding);
|
||||
uniformBufferSlotMap[info.binding] = info.index;
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& info : uniformBlocks) {
|
||||
if (slotBindings.count(info.name)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// If the binding is 0, or the binding maps to an already used binding
|
||||
if (info.binding == 0 || !isUnusedSlot(uniformBufferSlotMap[info.binding])) {
|
||||
// If no binding was assigned then just do it finding a free slot
|
||||
auto slotIt = std::find_if(uniformBufferSlotMap.begin(), uniformBufferSlotMap.end(), GLBackend::isUnusedSlot);
|
||||
if (slotIt != uniformBufferSlotMap.end()) {
|
||||
info.binding = slotIt - uniformBufferSlotMap.begin();
|
||||
glUniformBlockBinding(glprogram, info.index, info.binding);
|
||||
} else {
|
||||
// This should neve happen, an active ubo cannot find an available slot among the max available?!
|
||||
info.binding = -1;
|
||||
}
|
||||
}
|
||||
|
||||
uniformBufferSlotMap[info.binding] = info.index;
|
||||
}
|
||||
|
||||
for (auto& info : uniformBlocks) {
|
||||
static const Element element(SCALAR, gpu::UINT32, gpu::UNIFORM_BUFFER);
|
||||
buffers.insert(Shader::Slot(info.name, info.binding, element, Resource::BUFFER, info.size));
|
||||
}
|
||||
return buffersCount;
|
||||
}
|
||||
|
||||
int GLBackend::makeInputSlots(const ShaderObject& shaderProgram, const Shader::BindingSet& slotBindings, Shader::SlotSet& inputs) {
|
||||
const auto& glprogram = shaderProgram.glprogram;
|
||||
GLint inputsCount = 0;
|
||||
|
||||
glGetProgramiv(glprogram, GL_ACTIVE_ATTRIBUTES, &inputsCount);
|
||||
|
||||
for (int i = 0; i < inputsCount; i++) {
|
||||
const GLint NAME_LENGTH = 256;
|
||||
GLchar name[NAME_LENGTH];
|
||||
GLint length = 0;
|
||||
GLint size = 0;
|
||||
GLenum type = 0;
|
||||
glGetActiveAttrib(glprogram, i, NAME_LENGTH, &length, &size, &type, name);
|
||||
|
||||
GLint binding = glGetAttribLocation(glprogram, name);
|
||||
|
||||
auto elementResource = getFormatFromGLUniform(type);
|
||||
inputs.insert(Shader::Slot(name, binding, elementResource._element, -1));
|
||||
}
|
||||
|
||||
return inputsCount;
|
||||
}
|
||||
|
||||
int GLBackend::makeOutputSlots(const ShaderObject& shaderProgram, const Shader::BindingSet& slotBindings, Shader::SlotSet& outputs) {
|
||||
/* GLint outputsCount = 0;
|
||||
|
||||
glGetProgramiv(glprogram, GL_ACTIVE_, &outputsCount);
|
||||
|
||||
for (int i = 0; i < inputsCount; i++) {
|
||||
const GLint NAME_LENGTH = 256;
|
||||
GLchar name[NAME_LENGTH];
|
||||
GLint length = 0;
|
||||
GLint size = 0;
|
||||
GLenum type = 0;
|
||||
glGetActiveAttrib(glprogram, i, NAME_LENGTH, &length, &size, &type, name);
|
||||
|
||||
auto element = getFormatFromGLUniform(type);
|
||||
outputs.insert(Shader::Slot(name, i, element));
|
||||
}
|
||||
*/
|
||||
return 0; //inputsCount;
|
||||
}
|
||||
|
||||
void GLBackend::makeProgramBindings(ShaderObject& shaderObject) {
|
||||
if (!shaderObject.glprogram) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void GLBackend::initShaderBinaryCache() {
|
||||
GLint numBinFormats = 0;
|
||||
glGetIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS, &numBinFormats);
|
||||
|
|
|
@ -168,9 +168,8 @@ void GLBackend::TransformStageState::update(size_t commandIndex, const StereoSta
|
|||
|
||||
void GLBackend::TransformStageState::bindCurrentCamera(int eye) const {
|
||||
if (_currentCameraOffset != INVALID_OFFSET) {
|
||||
static_assert(TRANSFORM_CAMERA_SLOT >= MAX_NUM_UNIFORM_BUFFERS, "TransformCamera may overlap pipeline uniform buffer slots. Invalidate uniform buffer slot cache for safety (call _uniform._buffers[TRANSFORM_CAMERA_SLOT].reset()).");
|
||||
glBindBufferRange(GL_UNIFORM_BUFFER, TRANSFORM_CAMERA_SLOT, _cameraBuffer, _currentCameraOffset + eye * _cameraUboSize,
|
||||
sizeof(CameraBufferElement));
|
||||
static_assert(slot::buffer::Buffer::CameraTransform >= MAX_NUM_UNIFORM_BUFFERS, "TransformCamera may overlap pipeline uniform buffer slots. Invalidate uniform buffer slot cache for safety (call _uniform._buffers[TRANSFORM_CAMERA_SLOT].reset()).");
|
||||
glBindBufferRange(GL_UNIFORM_BUFFER, slot::buffer::Buffer::CameraTransform, _cameraBuffer, _currentCameraOffset + eye * _cameraUboSize, sizeof(CameraBufferElement));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
|
||||
#include "GLShader.h"
|
||||
#include "GLState.h"
|
||||
#include "GLBackend.h"
|
||||
|
||||
using namespace gpu;
|
||||
using namespace gpu::gl;
|
||||
|
@ -51,7 +52,7 @@ GLPipeline* GLPipeline::sync(GLBackend& backend, const Pipeline& pipeline) {
|
|||
// Special case for view correction matrices, any pipeline that declares the correction buffer
|
||||
// uniform will automatically have it provided without any client code necessary.
|
||||
// Required for stable lighting in the HMD.
|
||||
object->_cameraCorrection = shader->getUniformBuffers().findLocation("cameraCorrectionBuffer");
|
||||
object->_cameraCorrection = shader->getUniformBuffers().isValid(gpu::slot::buffer::CameraCorrection);
|
||||
object->_program = programObject;
|
||||
object->_state = stateObject;
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ public:
|
|||
GLState* _state { nullptr };
|
||||
// Bit of a hack, any pipeline can need the camera correction buffer at execution time, so
|
||||
// we store whether a given pipeline has declared the uniform buffer for it.
|
||||
int32 _cameraCorrection { -1 };
|
||||
bool _cameraCorrection{ false };
|
||||
};
|
||||
|
||||
} }
|
||||
|
|
|
@ -56,52 +56,5 @@ GLShader* GLShader::sync(GLBackend& backend, const Shader& shader, const Shader:
|
|||
return object;
|
||||
}
|
||||
|
||||
bool GLShader::makeProgram(GLBackend& backend, Shader& shader, const Shader::BindingSet& slotBindings, const Shader::CompilationHandler& handler) {
|
||||
|
||||
// First make sure the Shader has been compiled
|
||||
GLShader* object = sync(backend, shader, handler);
|
||||
if (!object) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Apply bindings to all program versions and generate list of slots from default version
|
||||
for (int version = 0; version < GLShader::NumVersions; version++) {
|
||||
auto& shaderObject = object->_shaderObjects[version];
|
||||
if (shaderObject.glprogram) {
|
||||
shaderObject.uniforms = ::gl::loadUniforms(shaderObject.glprogram);
|
||||
Shader::SlotSet buffers;
|
||||
backend.makeUniformBlockSlots(shaderObject, slotBindings, buffers);
|
||||
|
||||
Shader::SlotSet uniforms;
|
||||
Shader::SlotSet textures;
|
||||
Shader::SlotSet samplers;
|
||||
backend.makeUniformSlots(shaderObject, slotBindings, uniforms, textures, samplers);
|
||||
|
||||
Shader::SlotSet resourceBuffers;
|
||||
backend.makeResourceBufferSlots(shaderObject, slotBindings, resourceBuffers);
|
||||
|
||||
Shader::SlotSet inputs;
|
||||
backend.makeInputSlots(shaderObject, slotBindings, inputs);
|
||||
|
||||
Shader::SlotSet outputs;
|
||||
backend.makeOutputSlots(shaderObject, slotBindings, outputs);
|
||||
|
||||
// Define the public slots only from the default version
|
||||
if (version == 0) {
|
||||
shader.defineSlots(uniforms, buffers, resourceBuffers, textures, samplers, inputs, outputs);
|
||||
} // else
|
||||
{
|
||||
GLShader::UniformMapping mapping;
|
||||
for (auto srcUniform : shader.getUniforms()) {
|
||||
mapping[srcUniform._location] = uniforms.findLocation(srcUniform._name);
|
||||
}
|
||||
object->_uniformMappings.push_back(mapping);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -14,18 +14,16 @@
|
|||
namespace gpu { namespace gl {
|
||||
|
||||
struct ShaderObject {
|
||||
using Uniforms = ::gl::Uniforms;
|
||||
GLuint glshader { 0 };
|
||||
GLuint glprogram { 0 };
|
||||
GLint transformCameraSlot { -1 };
|
||||
GLint transformObjectSlot { -1 };
|
||||
Uniforms uniforms;
|
||||
|
||||
using LocationMap = std::unordered_map <GLuint, GLuint>;
|
||||
LocationMap uniformRemap;
|
||||
};
|
||||
|
||||
class GLShader : public GPUObject {
|
||||
public:
|
||||
static GLShader* sync(GLBackend& backend, const Shader& shader, const Shader::CompilationHandler& handler = nullptr);
|
||||
static bool makeProgram(GLBackend& backend, Shader& shader, const Shader::BindingSet& slotBindings, const Shader::CompilationHandler& handler);
|
||||
|
||||
enum Version {
|
||||
Mono = 0,
|
||||
|
@ -44,22 +42,11 @@ public:
|
|||
~GLShader();
|
||||
|
||||
ShaderObjects _shaderObjects;
|
||||
UniformMappingVersions _uniformMappings;
|
||||
|
||||
GLuint getProgram(Version version = Mono) const {
|
||||
return _shaderObjects[version].glprogram;
|
||||
}
|
||||
|
||||
GLint getUniformLocation(GLint srcLoc, Version version = Mono) const {
|
||||
// This check protect against potential invalid src location for this shader, if unknown then return -1.
|
||||
const auto& mapping = _uniformMappings[version];
|
||||
auto found = mapping.find(srcLoc);
|
||||
if (found == mapping.end()) {
|
||||
return -1;
|
||||
}
|
||||
return found->second;
|
||||
}
|
||||
|
||||
const std::weak_ptr<GLBackend> _backend;
|
||||
};
|
||||
|
||||
|
|
|
@ -129,9 +129,10 @@ void GLBackend::killTextureManagementStage() {
|
|||
}
|
||||
|
||||
std::vector<TexturePointer> GLTextureTransferEngine::getAllTextures() {
|
||||
std::remove_if(_registeredTextures.begin(), _registeredTextures.end(), [&](const std::weak_ptr<Texture>& weak) -> bool {
|
||||
return weak.expired();
|
||||
auto expiredBegin = std::remove_if(_registeredTextures.begin(), _registeredTextures.end(), [&](const std::weak_ptr<Texture>& weak) -> bool {
|
||||
return weak.expired();
|
||||
});
|
||||
_registeredTextures.erase(expiredBegin, _registeredTextures.end());
|
||||
|
||||
std::vector<TexturePointer> result;
|
||||
result.reserve(_registeredTextures.size());
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
#include <shared/GlobalAppProperties.h>
|
||||
#include <gl/QOpenGLContextWrapper.h>
|
||||
#include <gl/GLHelpers.h>
|
||||
#include <gpu/gl/GLShader.h>
|
||||
|
||||
#include "../gl41/GL41Backend.h"
|
||||
|
@ -24,9 +25,6 @@
|
|||
using namespace gpu;
|
||||
using namespace gpu::gl;
|
||||
|
||||
static const QString DEBUG_FLAG("HIFI_DISABLE_OPENGL_45");
|
||||
static bool disableOpenGL45 = QProcessEnvironment::systemEnvironment().contains(DEBUG_FLAG);
|
||||
|
||||
static GLBackend* INSTANCE{ nullptr };
|
||||
|
||||
BackendPointer GLBackend::createBackend() {
|
||||
|
@ -34,7 +32,7 @@ BackendPointer GLBackend::createBackend() {
|
|||
// Where the gpuContext is initialized and where the TRUE Backend is created and assigned
|
||||
auto version = QOpenGLContextWrapper::currentContextVersion();
|
||||
std::shared_ptr<GLBackend> result;
|
||||
if (!disableOpenGL45 && version >= 0x0405) {
|
||||
if (!::gl::disableGl45() && version >= 0x0405) {
|
||||
qCDebug(gpugllogging) << "Using OpenGL 4.5 backend";
|
||||
result = std::make_shared<gpu::gl45::GL45Backend>();
|
||||
} else {
|
||||
|
@ -57,7 +55,3 @@ GLBackend& getBackend() {
|
|||
}
|
||||
return *INSTANCE;
|
||||
}
|
||||
|
||||
bool GLBackend::makeProgram(Shader& shader, const Shader::BindingSet& slotBindings, const Shader::CompilationHandler& handler) {
|
||||
return GLShader::makeProgram(getBackend(), shader, slotBindings, handler);
|
||||
}
|
||||
|
|
|
@ -19,11 +19,7 @@
|
|||
#define GPU_CORE_41 410
|
||||
#define GPU_CORE_43 430
|
||||
|
||||
#ifdef Q_OS_MAC
|
||||
#define GPU_INPUT_PROFILE GPU_CORE_41
|
||||
#else
|
||||
#define GPU_INPUT_PROFILE GPU_CORE_43
|
||||
#endif
|
||||
|
||||
namespace gpu { namespace gl41 {
|
||||
|
||||
|
@ -35,7 +31,6 @@ class GL41Backend : public GLBackend {
|
|||
friend class Context;
|
||||
|
||||
public:
|
||||
static const GLint TRANSFORM_OBJECT_SLOT { 31 };
|
||||
static const GLint RESOURCE_TRANSFER_TEX_UNIT { 32 };
|
||||
static const GLint RESOURCE_TRANSFER_EXTRA_TEX_UNIT { 33 };
|
||||
static const GLint RESOURCE_BUFFER_TEXBUF_TEX_UNIT { 34 };
|
||||
|
@ -172,9 +167,8 @@ protected:
|
|||
void do_blit(const Batch& batch, size_t paramOffset) override;
|
||||
|
||||
std::string getBackendShaderHeader() const override;
|
||||
void makeProgramBindings(ShaderObject& shaderObject) override;
|
||||
int makeResourceBufferSlots(const ShaderObject& shaderProgram, const Shader::BindingSet& slotBindings,Shader::SlotSet& resourceBuffers) override;
|
||||
|
||||
void postLinkProgram(ShaderObject& programObject, const Shader& program) const override;
|
||||
};
|
||||
|
||||
} }
|
||||
|
|
|
@ -22,90 +22,54 @@ std::string GL41Backend::getBackendShaderHeader() const {
|
|||
return header;
|
||||
}
|
||||
|
||||
int GL41Backend::makeResourceBufferSlots(const ShaderObject& shaderProgram, const Shader::BindingSet& slotBindings,Shader::SlotSet& resourceBuffers) {
|
||||
GLint ssboCount = 0;
|
||||
const auto& glprogram = shaderProgram.glprogram;
|
||||
for (const auto& uniform : shaderProgram.uniforms) {
|
||||
const auto& name = uniform.name;
|
||||
const auto& type = uniform.type;
|
||||
const auto& location = uniform.location;
|
||||
const GLint INVALID_UNIFORM_LOCATION = -1;
|
||||
|
||||
// Try to make sense of the gltype
|
||||
auto elementResource = getFormatFromGLUniform(type);
|
||||
|
||||
// The uniform as a standard var type
|
||||
if (location != INVALID_UNIFORM_LOCATION) {
|
||||
|
||||
if (elementResource._resource == Resource::BUFFER) {
|
||||
if (elementResource._element.getSemantic() == gpu::RESOURCE_BUFFER) {
|
||||
// Let's make sure the name doesn't contains an array element
|
||||
std::string sname(name);
|
||||
auto foundBracket = sname.find_first_of('[');
|
||||
if (foundBracket != std::string::npos) {
|
||||
// std::string arrayname = sname.substr(0, foundBracket);
|
||||
|
||||
if (sname[foundBracket + 1] == '0') {
|
||||
sname = sname.substr(0, foundBracket);
|
||||
} else {
|
||||
// skip this uniform since it's not the first element of an array
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// For texture/Sampler, the location is the actual binding value
|
||||
GLint binding = -1;
|
||||
glGetUniformiv(glprogram, location, &binding);
|
||||
|
||||
if (binding == GL41Backend::TRANSFORM_OBJECT_SLOT) {
|
||||
continue;
|
||||
}
|
||||
|
||||
auto requestedBinding = slotBindings.find(std::string(sname));
|
||||
if (requestedBinding != slotBindings.end()) {
|
||||
GLint requestedLoc = (*requestedBinding)._location + GL41Backend::RESOURCE_BUFFER_SLOT0_TEX_UNIT;
|
||||
if (binding != requestedLoc) {
|
||||
binding = requestedLoc;
|
||||
}
|
||||
} else {
|
||||
binding += GL41Backend::RESOURCE_BUFFER_SLOT0_TEX_UNIT;
|
||||
}
|
||||
glProgramUniform1i(glprogram, location, binding);
|
||||
|
||||
ssboCount++;
|
||||
resourceBuffers.insert(Shader::Slot(name, binding, elementResource._element, elementResource._resource));
|
||||
}
|
||||
void GL41Backend::postLinkProgram(ShaderObject& programObject, const Shader& program) const {
|
||||
Parent::postLinkProgram(programObject, program);
|
||||
const auto& glprogram = programObject.glprogram;
|
||||
// For the UBOs, use glUniformBlockBinding to fixup the locations based on the reflection
|
||||
{
|
||||
const auto expectedUbos = program.getUniformBuffers().getLocationsByName();
|
||||
auto ubos = ::gl::UniformBlock::load(glprogram);
|
||||
for (const auto& ubo : ubos) {
|
||||
const auto& name = ubo.name;
|
||||
if (0 == expectedUbos.count(name)) {
|
||||
continue;
|
||||
}
|
||||
const auto& targetLocation = expectedUbos.at(name);
|
||||
glUniformBlockBinding(glprogram, ubo.index, targetLocation);
|
||||
}
|
||||
}
|
||||
|
||||
return ssboCount;
|
||||
// For the Textures, use glUniform1i to fixup the active texture slots based on the reflection
|
||||
{
|
||||
const auto expectedTextures = program.getTextures().getLocationsByName();
|
||||
for (const auto& expectedTexture : expectedTextures) {
|
||||
auto location = glGetUniformLocation(glprogram, expectedTexture.first.c_str());
|
||||
if (location < 0) {
|
||||
continue;
|
||||
}
|
||||
glProgramUniform1i(glprogram, location, expectedTexture.second);
|
||||
}
|
||||
}
|
||||
|
||||
// For the resource buffers, do the same as for the textures, since in GL 4.1 that's how they're implemented
|
||||
{
|
||||
const auto expectedResourceBuffers = program.getResourceBuffers().getLocationsByName();
|
||||
const auto resourceBufferUniforms = ::gl::Uniform::loadByName(glprogram, program.getResourceBuffers().getNames());
|
||||
for (const auto& resourceBuffer : resourceBufferUniforms) {
|
||||
const auto& targetBinding = expectedResourceBuffers.at(resourceBuffer.name);
|
||||
glProgramUniform1i(glprogram, resourceBuffer.binding, targetBinding);
|
||||
}
|
||||
}
|
||||
|
||||
// Special case for the transformObjectBuffer, which is filtered out of the reflection data at shader load time
|
||||
//
|
||||
{
|
||||
static const std::string TRANSFORM_OBJECT_BUFFER = "transformObjectBuffer";
|
||||
const auto uniform = ::gl::Uniform::loadByName(glprogram, TRANSFORM_OBJECT_BUFFER);
|
||||
if (-1 != uniform.binding) {
|
||||
glProgramUniform1i(glprogram, uniform.binding, ::gpu::slot::texture::ObjectTransforms);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GL41Backend::makeProgramBindings(ShaderObject& shaderObject) {
|
||||
if (!shaderObject.glprogram) {
|
||||
return;
|
||||
}
|
||||
GLuint glprogram = shaderObject.glprogram;
|
||||
GLint loc = -1;
|
||||
|
||||
GLBackend::makeProgramBindings(shaderObject);
|
||||
|
||||
// now assign the ubo binding, then DON't relink!
|
||||
|
||||
//Check for gpu specific uniform slotBindings
|
||||
loc = glGetUniformLocation(glprogram, "transformObjectBuffer");
|
||||
if (loc >= 0) {
|
||||
glProgramUniform1i(glprogram, loc, GL41Backend::TRANSFORM_OBJECT_SLOT);
|
||||
shaderObject.transformObjectSlot = GL41Backend::TRANSFORM_OBJECT_SLOT;
|
||||
}
|
||||
|
||||
loc = glGetUniformBlockIndex(glprogram, "transformCameraBuffer");
|
||||
if (loc >= 0) {
|
||||
glUniformBlockBinding(glprogram, loc, gpu::TRANSFORM_CAMERA_SLOT);
|
||||
shaderObject.transformCameraSlot = gpu::TRANSFORM_CAMERA_SLOT;
|
||||
}
|
||||
|
||||
(void)CHECK_GL_ERROR();
|
||||
}
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ void GL41Backend::initTransform() {
|
|||
glGenTextures(1, &_transform._objectBufferTexture);
|
||||
size_t cameraSize = sizeof(TransformStageState::CameraBufferElement);
|
||||
while (_transform._cameraUboSize < cameraSize) {
|
||||
_transform._cameraUboSize += _uboAlignment;
|
||||
_transform._cameraUboSize += UNIFORM_BUFFER_OFFSET_ALIGNMENT;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -58,7 +58,7 @@ void GL41Backend::transferTransformState(const Batch& batch) const {
|
|||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
}
|
||||
|
||||
glActiveTexture(GL_TEXTURE0 + GL41Backend::TRANSFORM_OBJECT_SLOT);
|
||||
glActiveTexture(GL_TEXTURE0 + slot::texture::ObjectTransforms);
|
||||
glBindTexture(GL_TEXTURE_BUFFER, _transform._objectBufferTexture);
|
||||
if (!batch._objects.empty()) {
|
||||
glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, _transform._objectBuffer);
|
||||
|
|
|
@ -18,8 +18,26 @@ Q_LOGGING_CATEGORY(gpugl45logging, "hifi.gpu.gl45")
|
|||
using namespace gpu;
|
||||
using namespace gpu::gl45;
|
||||
|
||||
GLint GL45Backend::MAX_COMBINED_SHADER_STORAGE_BLOCKS{ 0 };
|
||||
GLint GL45Backend::MAX_UNIFORM_LOCATIONS{ 0 };
|
||||
|
||||
static void staticInit() {
|
||||
static std::once_flag once;
|
||||
std::call_once(once, [&] {
|
||||
glGetIntegerv(GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS, &GL45Backend::MAX_COMBINED_SHADER_STORAGE_BLOCKS);
|
||||
glGetIntegerv(GL_MAX_UNIFORM_LOCATIONS, &GL45Backend::MAX_UNIFORM_LOCATIONS);
|
||||
});
|
||||
}
|
||||
const std::string GL45Backend::GL45_VERSION { "GL45" };
|
||||
|
||||
GL45Backend::GL45Backend(bool syncCache) : Parent(syncCache) {
|
||||
staticInit();
|
||||
}
|
||||
|
||||
GL45Backend::GL45Backend() : Parent() {
|
||||
staticInit();
|
||||
}
|
||||
|
||||
void GL45Backend::recycle() const {
|
||||
Parent::recycle();
|
||||
}
|
||||
|
|
|
@ -33,18 +33,14 @@ class GL45Backend : public GLBackend {
|
|||
friend class Context;
|
||||
|
||||
public:
|
||||
static GLint MAX_COMBINED_SHADER_STORAGE_BLOCKS;
|
||||
static GLint MAX_UNIFORM_LOCATIONS;
|
||||
#if GPU_BINDLESS_TEXTURES
|
||||
virtual bool supportsBindless() const override { return true; }
|
||||
#endif
|
||||
|
||||
#ifdef GPU_SSBO_TRANSFORM_OBJECT
|
||||
static const GLint TRANSFORM_OBJECT_SLOT { 14 }; // SSBO binding slot
|
||||
#else
|
||||
static const GLint TRANSFORM_OBJECT_SLOT { 31 }; // TBO binding slot
|
||||
#endif
|
||||
|
||||
explicit GL45Backend(bool syncCache) : Parent(syncCache) {}
|
||||
GL45Backend() : Parent() {}
|
||||
explicit GL45Backend(bool syncCache);
|
||||
GL45Backend();
|
||||
virtual ~GL45Backend() {
|
||||
// call resetStages here rather than in ~GLBackend dtor because it will call releaseResourceBuffer
|
||||
// which is pure virtual from GLBackend's dtor.
|
||||
|
@ -273,8 +269,6 @@ protected:
|
|||
|
||||
// Shader Stage
|
||||
std::string getBackendShaderHeader() const override;
|
||||
void makeProgramBindings(ShaderObject& shaderObject) override;
|
||||
int makeResourceBufferSlots(const ShaderObject& shaderProgram, const Shader::BindingSet& slotBindings,Shader::SlotSet& resourceBuffers) override;
|
||||
|
||||
// Texture Management Stage
|
||||
void initTextureManagementStage() override;
|
||||
|
|
|
@ -26,152 +26,3 @@ std::string GL45Backend::getBackendShaderHeader() const {
|
|||
);
|
||||
return header;
|
||||
}
|
||||
|
||||
int GL45Backend::makeResourceBufferSlots(const ShaderObject& shaderProgram, const Shader::BindingSet& slotBindings,Shader::SlotSet& resourceBuffers) {
|
||||
const auto& glprogram = shaderProgram.glprogram;
|
||||
GLint buffersCount = 0;
|
||||
glGetProgramInterfaceiv(glprogram, GL_SHADER_STORAGE_BLOCK, GL_ACTIVE_RESOURCES, &buffersCount);
|
||||
|
||||
// fast exit
|
||||
if (buffersCount == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
GLint maxNumResourceBufferSlots = 0;
|
||||
glGetIntegerv(GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS, &maxNumResourceBufferSlots);
|
||||
std::vector<GLint> resourceBufferSlotMap(maxNumResourceBufferSlots, -1);
|
||||
|
||||
struct ResourceBlockInfo {
|
||||
using Vector = std::vector<ResourceBlockInfo>;
|
||||
const GLuint index{ 0 };
|
||||
const std::string name;
|
||||
GLint binding{ -1 };
|
||||
GLint size{ 0 };
|
||||
|
||||
static std::string getName(GLuint glprogram, GLuint i) {
|
||||
static const GLint NAME_LENGTH = 256;
|
||||
GLint length = 0;
|
||||
GLchar nameBuffer[NAME_LENGTH];
|
||||
glGetProgramResourceName(glprogram, GL_SHADER_STORAGE_BLOCK, i, NAME_LENGTH, &length, nameBuffer);
|
||||
return std::string(nameBuffer);
|
||||
}
|
||||
|
||||
ResourceBlockInfo(GLuint glprogram, GLuint i) : index(i), name(getName(glprogram, i)) {
|
||||
GLenum props[2] = { GL_BUFFER_BINDING, GL_BUFFER_DATA_SIZE};
|
||||
glGetProgramResourceiv(glprogram, GL_SHADER_STORAGE_BLOCK, i, 2, props, 2, nullptr, &binding);
|
||||
}
|
||||
};
|
||||
|
||||
ResourceBlockInfo::Vector resourceBlocks;
|
||||
resourceBlocks.reserve(buffersCount);
|
||||
for (int i = 0; i < buffersCount; i++) {
|
||||
resourceBlocks.push_back(ResourceBlockInfo(glprogram, i));
|
||||
}
|
||||
|
||||
for (auto& info : resourceBlocks) {
|
||||
auto requestedBinding = slotBindings.find(info.name);
|
||||
if (requestedBinding != slotBindings.end()) {
|
||||
info.binding = (*requestedBinding)._location;
|
||||
glShaderStorageBlockBinding(glprogram, info.index, info.binding);
|
||||
resourceBufferSlotMap[info.binding] = info.index;
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& info : resourceBlocks) {
|
||||
if (slotBindings.count(info.name)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// If the binding is -1, or the binding maps to an already used binding
|
||||
if (info.binding == -1 || !isUnusedSlot(resourceBufferSlotMap[info.binding])) {
|
||||
// If no binding was assigned then just do it finding a free slot
|
||||
auto slotIt = std::find_if(resourceBufferSlotMap.begin(), resourceBufferSlotMap.end(), GLBackend::isUnusedSlot);
|
||||
if (slotIt != resourceBufferSlotMap.end()) {
|
||||
info.binding = slotIt - resourceBufferSlotMap.begin();
|
||||
glShaderStorageBlockBinding(glprogram, info.index, info.binding);
|
||||
} else {
|
||||
// This should never happen, an active ssbo cannot find an available slot among the max available?!
|
||||
info.binding = -1;
|
||||
}
|
||||
}
|
||||
|
||||
resourceBufferSlotMap[info.binding] = info.index;
|
||||
}
|
||||
|
||||
for (auto& info : resourceBlocks) {
|
||||
static const Element element(SCALAR, gpu::UINT32, gpu::RESOURCE_BUFFER);
|
||||
resourceBuffers.insert(Shader::Slot(info.name, info.binding, element, Resource::BUFFER, info.size));
|
||||
}
|
||||
return buffersCount;
|
||||
/*
|
||||
GLint ssboCount = 0;
|
||||
glGetProgramInterfaceiv(glprogram, GL_SHADER_STORAGE_BLOCK, GL_ACTIVE_RESOURCES, &ssboCount);
|
||||
if (ssboCount > 0) {
|
||||
GLint maxNameLength = 0;
|
||||
glGetProgramInterfaceiv(glprogram, GL_SHADER_STORAGE_BLOCK, GL_MAX_NAME_LENGTH, &maxNameLength);
|
||||
std::vector<GLchar> nameBytes(maxNameLength);
|
||||
|
||||
for (GLint b = 0; b < ssboCount; b++) {
|
||||
GLint length;
|
||||
glGetProgramResourceName(glprogram, GL_SHADER_STORAGE_BLOCK, b, maxNameLength, &length, nameBytes.data());
|
||||
std::string bufferName(nameBytes.data());
|
||||
|
||||
GLenum props = GL_BUFFER_BINDING;
|
||||
GLint binding = -1;
|
||||
glGetProgramResourceiv(glprogram, GL_SHADER_STORAGE_BLOCK, b, 1, &props, 1, nullptr, &binding);
|
||||
|
||||
auto requestedBinding = slotBindings.find(std::string(bufferName));
|
||||
if (requestedBinding != slotBindings.end()) {
|
||||
if (binding != (*requestedBinding)._location) {
|
||||
binding = (*requestedBinding)._location;
|
||||
glShaderStorageBlockBinding(glprogram, b, binding);
|
||||
}
|
||||
}
|
||||
|
||||
static const Element element(SCALAR, gpu::UINT32, gpu::RESOURCE_BUFFER);
|
||||
resourceBuffers.insert(Shader::Slot(bufferName, binding, element, -1));
|
||||
}
|
||||
}
|
||||
return ssboCount;*/
|
||||
}
|
||||
|
||||
void GL45Backend::makeProgramBindings(ShaderObject& shaderObject) {
|
||||
if (!shaderObject.glprogram) {
|
||||
return;
|
||||
}
|
||||
GLuint glprogram = shaderObject.glprogram;
|
||||
GLint loc = -1;
|
||||
|
||||
GLBackend::makeProgramBindings(shaderObject);
|
||||
|
||||
// now assign the ubo binding, then DON't relink!
|
||||
|
||||
//Check for gpu specific uniform slotBindings
|
||||
#ifdef GPU_SSBO_TRANSFORM_OBJECT
|
||||
loc = glGetProgramResourceIndex(glprogram, GL_SHADER_STORAGE_BLOCK, "transformObjectBuffer");
|
||||
if (loc >= 0) {
|
||||
glShaderStorageBlockBinding(glprogram, loc, GL45Backend::TRANSFORM_OBJECT_SLOT);
|
||||
shaderObject.transformObjectSlot = GL45Backend::TRANSFORM_OBJECT_SLOT;
|
||||
}
|
||||
#else
|
||||
loc = glGetUniformLocation(glprogram, "transformObjectBuffer");
|
||||
if (loc >= 0) {
|
||||
glProgramUniform1i(glprogram, loc, GL45Backend::TRANSFORM_OBJECT_SLOT);
|
||||
shaderObject.transformObjectSlot = GL45Backend::TRANSFORM_OBJECT_SLOT;
|
||||
}
|
||||
#endif
|
||||
|
||||
loc = glGetUniformBlockIndex(glprogram, "transformCameraBuffer");
|
||||
if (loc >= 0) {
|
||||
glUniformBlockBinding(glprogram, loc, gpu::TRANSFORM_CAMERA_SLOT);
|
||||
shaderObject.transformCameraSlot = gpu::TRANSFORM_CAMERA_SLOT;
|
||||
}
|
||||
|
||||
loc = glGetUniformBlockIndex(glprogram, "gpu_resourceTextureTable0");
|
||||
if (loc >= 0) {
|
||||
glUniformBlockBinding(glprogram, loc, RESOURCE_TABLE_TEXTURE_SLOT_OFFSET);
|
||||
}
|
||||
|
||||
(void)CHECK_GL_ERROR();
|
||||
}
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@ void GL45Backend::initTransform() {
|
|||
#endif
|
||||
size_t cameraSize = sizeof(TransformStageState::CameraBufferElement);
|
||||
while (_transform._cameraUboSize < cameraSize) {
|
||||
_transform._cameraUboSize += _uboAlignment;
|
||||
_transform._cameraUboSize += UNIFORM_BUFFER_OFFSET_ALIGNMENT;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -57,9 +57,9 @@ void GL45Backend::transferTransformState(const Batch& batch) const {
|
|||
}
|
||||
|
||||
#ifdef GPU_SSBO_TRANSFORM_OBJECT
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, GL45Backend::TRANSFORM_OBJECT_SLOT, _transform._objectBuffer);
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, slot::storage::ObjectTransforms, _transform._objectBuffer);
|
||||
#else
|
||||
glActiveTexture(GL_TEXTURE0 + GL45Backend::TRANSFORM_OBJECT_SLOT);
|
||||
glActiveTexture(GL_TEXTURE0 + slot::texture::ObjectTransforms);
|
||||
glBindTexture(GL_TEXTURE_BUFFER, _transform._objectBufferTexture);
|
||||
glTextureBuffer(_transform._objectBufferTexture, GL_RGBA32F, _transform._objectBuffer);
|
||||
#endif
|
||||
|
|
|
@ -50,7 +50,3 @@ GLBackend& getBackend() {
|
|||
}
|
||||
return *INSTANCE;
|
||||
}
|
||||
|
||||
bool GLBackend::makeProgram(Shader& shader, const Shader::BindingSet& slotBindings, const Shader::CompilationHandler& handler) {
|
||||
return GLShader::makeProgram(getBackend(), shader, slotBindings, handler);
|
||||
}
|
||||
|
|
|
@ -163,9 +163,6 @@ protected:
|
|||
void do_blit(const Batch& batch, size_t paramOffset) override;
|
||||
|
||||
std::string getBackendShaderHeader() const override;
|
||||
void makeProgramBindings(ShaderObject& shaderObject) override;
|
||||
int makeResourceBufferSlots(const ShaderObject& shaderObject, const Shader::BindingSet& slotBindings,Shader::SlotSet& resourceBuffers) override;
|
||||
|
||||
};
|
||||
|
||||
} }
|
||||
|
@ -173,4 +170,4 @@ protected:
|
|||
Q_DECLARE_LOGGING_CATEGORY(gpugleslogging)
|
||||
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -24,93 +24,3 @@ std::string GLESBackend::getBackendShaderHeader() const {
|
|||
)SHADER");
|
||||
return header;
|
||||
}
|
||||
|
||||
int GLESBackend::makeResourceBufferSlots(const ShaderObject& shaderObject, const Shader::BindingSet& slotBindings,Shader::SlotSet& resourceBuffers) {
|
||||
GLint ssboCount = 0;
|
||||
GLint uniformsCount = 0;
|
||||
const auto& glprogram = shaderObject.glprogram;
|
||||
|
||||
for (const auto& uniform : shaderObject.uniforms) {
|
||||
const auto& type = uniform.type;
|
||||
const auto& location = uniform.location;
|
||||
const auto& name = uniform.name;
|
||||
const GLint INVALID_UNIFORM_LOCATION = -1;
|
||||
|
||||
// Try to make sense of the gltype
|
||||
auto elementResource = getFormatFromGLUniform(type);
|
||||
|
||||
// The uniform as a standard var type
|
||||
if (location != INVALID_UNIFORM_LOCATION) {
|
||||
|
||||
if (elementResource._resource == Resource::BUFFER) {
|
||||
if (elementResource._element.getSemantic() == gpu::RESOURCE_BUFFER) {
|
||||
// Let's make sure the name doesn't contains an array element
|
||||
std::string sname(name);
|
||||
auto foundBracket = sname.find_first_of('[');
|
||||
if (foundBracket != std::string::npos) {
|
||||
// std::string arrayname = sname.substr(0, foundBracket);
|
||||
|
||||
if (sname[foundBracket + 1] == '0') {
|
||||
sname = sname.substr(0, foundBracket);
|
||||
} else {
|
||||
// skip this uniform since it's not the first element of an array
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// For texture/Sampler, the location is the actual binding value
|
||||
GLint binding = -1;
|
||||
glGetUniformiv(glprogram, location, &binding);
|
||||
|
||||
if (binding == GLESBackend::TRANSFORM_OBJECT_SLOT) {
|
||||
continue;
|
||||
}
|
||||
|
||||
auto requestedBinding = slotBindings.find(std::string(sname));
|
||||
if (requestedBinding != slotBindings.end()) {
|
||||
GLint requestedLoc = (*requestedBinding)._location + GLESBackend::RESOURCE_BUFFER_SLOT0_TEX_UNIT;
|
||||
if (binding != requestedLoc) {
|
||||
binding = requestedLoc;
|
||||
}
|
||||
} else {
|
||||
binding += GLESBackend::RESOURCE_BUFFER_SLOT0_TEX_UNIT;
|
||||
}
|
||||
glProgramUniform1i(glprogram, location, binding);
|
||||
|
||||
ssboCount++;
|
||||
resourceBuffers.insert(Shader::Slot(name, binding, elementResource._element, elementResource._resource));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ssboCount;
|
||||
}
|
||||
|
||||
void GLESBackend::makeProgramBindings(ShaderObject& shaderObject) {
|
||||
if (!shaderObject.glprogram) {
|
||||
return;
|
||||
}
|
||||
GLuint glprogram = shaderObject.glprogram;
|
||||
GLint loc = -1;
|
||||
|
||||
GLBackend::makeProgramBindings(shaderObject);
|
||||
|
||||
// now assign the ubo binding, then DON't relink!
|
||||
|
||||
//Check for gpu specific uniform slotBindings
|
||||
loc = glGetUniformLocation(glprogram, "transformObjectBuffer");
|
||||
if (loc >= 0) {
|
||||
glProgramUniform1i(glprogram, loc, GLESBackend::TRANSFORM_OBJECT_SLOT);
|
||||
shaderObject.transformObjectSlot = GLESBackend::TRANSFORM_OBJECT_SLOT;
|
||||
}
|
||||
|
||||
loc = glGetUniformBlockIndex(glprogram, "transformCameraBuffer");
|
||||
if (loc >= 0) {
|
||||
glUniformBlockBinding(glprogram, loc, gpu::TRANSFORM_CAMERA_SLOT);
|
||||
shaderObject.transformCameraSlot = gpu::TRANSFORM_CAMERA_SLOT;
|
||||
}
|
||||
|
||||
(void)CHECK_GL_ERROR();
|
||||
}
|
||||
|
||||
|
|
|
@ -19,8 +19,10 @@ void GLESBackend::initTransform() {
|
|||
glGenBuffers(1, &_transform._drawCallInfoBuffer);
|
||||
glGenTextures(1, &_transform._objectBufferTexture);
|
||||
size_t cameraSize = sizeof(TransformStageState::CameraBufferElement);
|
||||
while (_transform._cameraUboSize < cameraSize) {
|
||||
_transform._cameraUboSize += _uboAlignment;
|
||||
if (UNIFORM_BUFFER_OFFSET_ALIGNMENT > 0) {
|
||||
while (_transform._cameraUboSize < cameraSize) {
|
||||
_transform._cameraUboSize += UNIFORM_BUFFER_OFFSET_ALIGNMENT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
set(TARGET_NAME gpu)
|
||||
autoscribe_shader_lib(gpu)
|
||||
|
||||
setup_hifi_library()
|
||||
link_hifi_libraries(shared ktx)
|
||||
link_hifi_libraries(shared ktx shaders)
|
||||
|
||||
target_nsight()
|
||||
|
|
|
@ -24,15 +24,12 @@
|
|||
#include "Stream.h"
|
||||
#include "Texture.h"
|
||||
#include "Transform.h"
|
||||
#include "ShaderConstants.h"
|
||||
|
||||
class QDebug;
|
||||
#define BATCH_PREALLOCATE_MIN 128
|
||||
namespace gpu {
|
||||
|
||||
enum ReservedSlot {
|
||||
TRANSFORM_CAMERA_SLOT = 15,
|
||||
};
|
||||
|
||||
// The named batch data provides a mechanism for accumulating data into buffers over the course
|
||||
// of many independent calls. For instance, two objects in the scene might both want to render
|
||||
// a simple box, but are otherwise unaware of each other. The common code that they call to render
|
||||
|
@ -170,10 +167,10 @@ public:
|
|||
void resetViewTransform() { setViewTransform(Transform(), false); }
|
||||
void setViewTransform(const Transform& view, bool camera = true);
|
||||
void setProjectionTransform(const Mat4& proj);
|
||||
void setProjectionJitter(float jx = 0.0f, float jy = 0.0f);
|
||||
// Very simple 1 level stack management of jitter.
|
||||
void pushProjectionJitter(float jx = 0.0f, float jy = 0.0f);
|
||||
void popProjectionJitter();
|
||||
void setProjectionJitter(float jx = 0.0f, float jy = 0.0f);
|
||||
// Very simple 1 level stack management of jitter.
|
||||
void pushProjectionJitter(float jx = 0.0f, float jy = 0.0f);
|
||||
void popProjectionJitter();
|
||||
// Viewport is xy = low left corner in framebuffer, zw = width height of the viewport, expressed in pixels
|
||||
void setViewportTransform(const Vec4i& viewport);
|
||||
void setDepthRangeTransform(float nearDepth, float farDepth);
|
||||
|
@ -299,9 +296,9 @@ public:
|
|||
|
||||
COMMAND_setModelTransform,
|
||||
COMMAND_setViewTransform,
|
||||
COMMAND_setProjectionTransform,
|
||||
COMMAND_setProjectionJitter,
|
||||
COMMAND_setViewportTransform,
|
||||
COMMAND_setProjectionTransform,
|
||||
COMMAND_setProjectionJitter,
|
||||
COMMAND_setViewportTransform,
|
||||
COMMAND_setDepthRangeTransform,
|
||||
|
||||
COMMAND_setPipeline,
|
||||
|
@ -504,7 +501,7 @@ public:
|
|||
|
||||
NamedBatchDataMap _namedData;
|
||||
|
||||
glm::vec2 _projectionJitter{ 0.0f, 0.0f };
|
||||
glm::vec2 _projectionJitter{ 0.0f, 0.0f };
|
||||
bool _enableStereo{ true };
|
||||
bool _enableSkybox { false };
|
||||
|
||||
|
|
|
@ -34,7 +34,6 @@ void ContextStats::evalDelta(const ContextStats& begin, const ContextStats& end)
|
|||
|
||||
|
||||
Context::CreateBackend Context::_createBackendCallback = nullptr;
|
||||
Context::MakeProgram Context::_makeProgramCallback = nullptr;
|
||||
std::once_flag Context::_initialized;
|
||||
|
||||
Context::Context() {
|
||||
|
@ -139,20 +138,6 @@ void Context::executeFrame(const FramePointer& frame) const {
|
|||
_frameStats.evalDelta(beginStats, endStats);
|
||||
}
|
||||
|
||||
bool Context::makeProgram(Shader& shader, const Shader::BindingSet& bindings, const Shader::CompilationHandler& handler) {
|
||||
PROFILE_RANGE_EX(app, "makeProgram", 0xff4040c0, shader.getID());
|
||||
// If we're running in another DLL context, we need to fetch the program callback out of the application
|
||||
// FIXME find a way to do this without reliance on Qt app properties
|
||||
if (!_makeProgramCallback) {
|
||||
void* rawCallback = qApp->property(hifi::properties::gl::MAKE_PROGRAM_CALLBACK).value<void*>();
|
||||
_makeProgramCallback = reinterpret_cast<Context::MakeProgram>(rawCallback);
|
||||
}
|
||||
if (shader.isProgram() && _makeProgramCallback) {
|
||||
return _makeProgramCallback(shader, bindings, handler);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void Context::enableStereo(bool enable) {
|
||||
_stereo._enable = enable;
|
||||
}
|
||||
|
|
|
@ -115,7 +115,7 @@ public:
|
|||
static ContextMetricSize textureResourceIdealGPUMemSize;
|
||||
|
||||
protected:
|
||||
virtual bool isStereo() {
|
||||
virtual bool isStereo() const {
|
||||
return _stereo.isStereo();
|
||||
}
|
||||
|
||||
|
@ -140,14 +140,12 @@ class Context {
|
|||
public:
|
||||
using Size = Resource::Size;
|
||||
typedef BackendPointer (*CreateBackend)();
|
||||
typedef bool (*MakeProgram)(Shader& shader, const Shader::BindingSet& bindings, const Shader::CompilationHandler& handler);
|
||||
|
||||
// This one call must happen before any context is created or used (Shader::MakeProgram) in order to setup the Backend and any singleton data needed
|
||||
template <class T>
|
||||
static void init() {
|
||||
std::call_once(_initialized, [] {
|
||||
_createBackendCallback = T::createBackend;
|
||||
_makeProgramCallback = T::makeProgram;
|
||||
T::init();
|
||||
});
|
||||
}
|
||||
|
@ -261,14 +259,7 @@ protected:
|
|||
// Sampled at the end of every frame, the stats of all the counters
|
||||
mutable ContextStats _frameStats;
|
||||
|
||||
// This function can only be called by "static Shader::makeProgram()"
|
||||
// makeProgramShader(...) make a program shader ready to be used in a Batch.
|
||||
// It compiles the sub shaders, link them and defines the Slots and their bindings.
|
||||
// If the shader passed is not a program, nothing happens.
|
||||
static bool makeProgram(Shader& shader, const Shader::BindingSet& bindings, const Shader::CompilationHandler& handler);
|
||||
|
||||
static CreateBackend _createBackendCallback;
|
||||
static MakeProgram _makeProgramCallback;
|
||||
static std::once_flag _initialized;
|
||||
|
||||
friend class Shader;
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
<$VERSION_HEADER$>
|
||||
// Generated on <$_SCRIBE_DATE$>
|
||||
//
|
||||
// DrawColor.frag
|
||||
//
|
||||
// Draw with color uniform
|
||||
//
|
||||
// Created by Olivier Prat on 25/10/2017
|
||||
|
@ -10,9 +12,12 @@
|
|||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
uniform vec4 color;
|
||||
|
||||
out vec4 outFragColor;
|
||||
<@include gpu/ShaderConstants.h@>
|
||||
|
||||
layout(location=GPU_UNIFORM_COLOR) uniform vec4 color;
|
||||
|
||||
layout(location=0) out vec4 outFragColor;
|
||||
|
||||
void main(void) {
|
||||
outFragColor = color;
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
<$VERSION_HEADER$>
|
||||
// Generated on <$_SCRIBE_DATE$>
|
||||
//
|
||||
// DrawColoredTexture.frag
|
||||
//
|
||||
// Draw texture 0 fetched at texcoord.xy, Blend with color uniform
|
||||
//
|
||||
// Created by Sam Gateau on 7/12/2015
|
||||
|
@ -11,12 +13,13 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
<@include gpu/ShaderConstants.h@>
|
||||
|
||||
uniform sampler2D colorMap;
|
||||
uniform vec4 color;
|
||||
layout(binding=0) uniform sampler2D colorMap;
|
||||
layout(location=GPU_UNIFORM_COLOR) uniform vec4 color;
|
||||
|
||||
in vec2 varTexCoord0;
|
||||
out vec4 outFragColor;
|
||||
layout(location=0) in vec2 varTexCoord0;
|
||||
layout(location=0) out vec4 outFragColor;
|
||||
|
||||
void main(void) {
|
||||
outFragColor = texture(colorMap, varTexCoord0) * color;
|
||||
|
|
5
libraries/gpu/src/gpu/DrawNada.slf
Normal file
5
libraries/gpu/src/gpu/DrawNada.slf
Normal file
|
@ -0,0 +1,5 @@
|
|||
<@include gpu/Config.slh@>
|
||||
|
||||
<$VERSION_HEADER$>
|
||||
|
||||
void main(void) { }
|
|
@ -1,6 +1,9 @@
|
|||
<@include gpu/Config.slh@>
|
||||
<$VERSION_HEADER$>
|
||||
// Generated on <$_SCRIBE_DATE$>
|
||||
//
|
||||
// DrawTexcoordRectTransformUnitQuad.vert
|
||||
|
||||
//
|
||||
// Draw and transform the unit quad [-1,-1 -> 1,1]
|
||||
// Transform the normalized texcoords [0, 1] to be in the range [texcoordRect.xy, texcoordRect.xy + texcoordRect.zw]
|
||||
|
@ -14,12 +17,13 @@
|
|||
//
|
||||
|
||||
<@include gpu/Transform.slh@>
|
||||
<@include gpu/ShaderConstants.h@>
|
||||
|
||||
<$declareStandardTransform()$>
|
||||
|
||||
uniform vec4 texcoordRect;
|
||||
layout(location=GPU_UNIFORM_TEXCOORD_RECT) uniform vec4 texcoordRect;
|
||||
|
||||
out vec2 varTexCoord0;
|
||||
layout(location=0) out vec2 varTexCoord0;
|
||||
|
||||
void main(void) {
|
||||
const vec4 UNIT_QUAD[4] = vec4[4](
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
<$VERSION_HEADER$>
|
||||
// Generated on <$_SCRIBE_DATE$>
|
||||
//
|
||||
// DrawTexture.frag
|
||||
//
|
||||
// Draw texture 0 fetched at texcoord.xy
|
||||
//
|
||||
// Created by Sam Gateau on 6/22/2015
|
||||
|
@ -12,10 +14,10 @@
|
|||
//
|
||||
|
||||
|
||||
uniform sampler2D colorMap;
|
||||
layout(binding=0) uniform sampler2D colorMap;
|
||||
|
||||
in vec2 varTexCoord0;
|
||||
out vec4 outFragColor;
|
||||
layout(location=0) in vec2 varTexCoord0;
|
||||
layout(location=0) out vec4 outFragColor;
|
||||
|
||||
void main(void) {
|
||||
outFragColor = texture(colorMap, varTexCoord0);
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
<$VERSION_HEADER$>
|
||||
// Generated on <$_SCRIBE_DATE$>
|
||||
//
|
||||
// DrawTextureMirroredX.frag
|
||||
//
|
||||
// Draw texture 0 fetched at (1.0 - texcoord.x, texcoord.y)
|
||||
//
|
||||
// Created by Sam Gondelman on 10/24/2017
|
||||
|
@ -12,10 +14,10 @@
|
|||
//
|
||||
|
||||
|
||||
uniform sampler2D colorMap;
|
||||
layout(binding=0) uniform sampler2D colorMap;
|
||||
|
||||
in vec2 varTexCoord0;
|
||||
out vec4 outFragColor;
|
||||
layout(location=0) in vec2 varTexCoord0;
|
||||
layout(location=0) out vec4 outFragColor;
|
||||
|
||||
void main(void) {
|
||||
outFragColor = texture(colorMap, vec2(1.0 - varTexCoord0.x, varTexCoord0.y));
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
<$VERSION_HEADER$>
|
||||
// Generated on <$_SCRIBE_DATE$>
|
||||
//
|
||||
// DrawTextureOpaque.frag
|
||||
//
|
||||
// Draw texture 0 fetched at texcoord.xy
|
||||
// Alpha is 1
|
||||
//
|
||||
|
@ -12,11 +14,13 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
<@include gpu/ShaderConstants.h@>
|
||||
|
||||
uniform sampler2D colorMap;
|
||||
layout(binding=0) uniform sampler2D colorMap;
|
||||
|
||||
in vec2 varTexCoord0;
|
||||
out vec4 outFragColor;
|
||||
layout(location=0) in vec2 varTexCoord0;
|
||||
|
||||
layout(location=0) out vec4 outFragColor;
|
||||
|
||||
void main(void) {
|
||||
outFragColor = vec4(texture(colorMap, varTexCoord0).xyz, 1.0);
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
<$VERSION_HEADER$>
|
||||
// Generated on <$_SCRIBE_DATE$>
|
||||
//
|
||||
// DrawTransformUnitQuad.vert
|
||||
//
|
||||
// Draw and transform the unit quad [-1,-1 -> 1,1]
|
||||
// Simply draw a Triangle_strip of 2 triangles, no input buffers or index buffer needed
|
||||
//
|
||||
|
@ -16,7 +18,7 @@
|
|||
|
||||
<$declareStandardTransform()$>
|
||||
|
||||
out vec2 varTexCoord0;
|
||||
layout(location=0) out vec2 varTexCoord0;
|
||||
|
||||
void main(void) {
|
||||
const vec4 UNIT_QUAD[4] = vec4[4](
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
<$VERSION_HEADER$>
|
||||
// Generated on <$_SCRIBE_DATE$>
|
||||
//
|
||||
// DrawTransformVertexPosition.vert
|
||||
//
|
||||
// Draw and transform the fed vertex position with the standard MVP stack
|
||||
// Output the clip position
|
||||
//
|
||||
|
@ -16,9 +18,9 @@
|
|||
|
||||
<$declareStandardTransform()$>
|
||||
|
||||
layout(location = 0) in vec4 inPosition;
|
||||
layout(location=0) in vec4 inPosition;
|
||||
|
||||
out vec3 varWorldPos;
|
||||
layout(location=0) out vec3 varWorldPos;
|
||||
|
||||
void main(void) {
|
||||
// standard transform
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
<$VERSION_HEADER$>
|
||||
// Generated on <$_SCRIBE_DATE$>
|
||||
//
|
||||
// DrawUnitQuadTexcoord.vert
|
||||
//
|
||||
// Draw the unit quad [-1,-1 -> 1,1] amd pass along the unit texcoords [0, 0 -> 1, 1]. Not transform used.
|
||||
// Simply draw a Triangle_strip of 2 triangles, no input buffers or index buffer needed
|
||||
//
|
||||
|
@ -11,7 +13,7 @@
|
|||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
out vec2 varTexCoord0;
|
||||
layout(location=0) out vec2 varTexCoord0;
|
||||
|
||||
void main(void) {
|
||||
const float depth = 1.0;
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
<$VERSION_HEADER$>
|
||||
// Generated on <$_SCRIBE_DATE$>
|
||||
//
|
||||
// DrawVertexPosition.vert
|
||||
//
|
||||
// Draw the fed vertex position, pass straight as clip pos
|
||||
// Output the clip position
|
||||
//
|
||||
|
@ -12,7 +14,7 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
layout(location = 0) in vec4 inPosition;
|
||||
layout(location=0) in vec4 inPosition;
|
||||
|
||||
void main(void) {
|
||||
gl_Position = inPosition;
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
<$VERSION_HEADER$>
|
||||
// Generated on <$_SCRIBE_DATE$>
|
||||
//
|
||||
// DrawViewportQuatTransformTexcoord.vert
|
||||
//
|
||||
// Draw the unit quad [-1,-1 -> 1,1] filling in
|
||||
// Simply draw a Triangle_strip of 2 triangles, no input buffers or index buffer needed
|
||||
//
|
||||
|
@ -16,7 +18,7 @@
|
|||
|
||||
<$declareStandardTransform()$>
|
||||
|
||||
out vec2 varTexCoord0;
|
||||
layout(location=0) out vec2 varTexCoord0;
|
||||
|
||||
void main(void) {
|
||||
const vec4 UNIT_QUAD[4] = vec4[4](
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<$VERSION_HEADER$>
|
||||
// Generated on <$_SCRIBE_DATE$>
|
||||
//
|
||||
// Draw white
|
||||
// DrawWhite.frag
|
||||
//
|
||||
// Created by Sam Gateau on 5/30/2017
|
||||
// Copyright 2017 High Fidelity, Inc.
|
||||
|
@ -11,7 +11,7 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
out vec4 outFragColor;
|
||||
layout(location=0) out vec4 outFragColor;
|
||||
|
||||
void main(void) {
|
||||
outFragColor = vec4(1.0);
|
||||
|
|
|
@ -10,15 +10,18 @@
|
|||
!>
|
||||
<@if not GPU_INPUTS_SLH@>
|
||||
<@def GPU_INPUTS_SLH@>
|
||||
layout(location = 0) in vec4 inPosition;
|
||||
layout(location = 1) in vec4 inNormal;
|
||||
layout(location = 2) in vec4 inColor;
|
||||
layout(location = 3) in vec4 inTexCoord0;
|
||||
layout(location = 4) in vec4 inTangent;
|
||||
layout(location = 5) in ivec4 inSkinClusterIndex;
|
||||
layout(location = 6) in vec4 inSkinClusterWeight;
|
||||
layout(location = 7) in vec4 inTexCoord1;
|
||||
layout(location = 8) in vec4 inTexCoord2;
|
||||
layout(location = 9) in vec4 inTexCoord3;
|
||||
layout(location = 10) in vec4 inTexCoord4;
|
||||
|
||||
<@include gpu/ShaderConstants.h@>
|
||||
|
||||
layout(location=GPU_ATTR_POSITION) in vec4 inPosition;
|
||||
layout(location=GPU_ATTR_NORMAL) in vec4 inNormal;
|
||||
layout(location=GPU_ATTR_COLOR) in vec4 inColor;
|
||||
layout(location=GPU_ATTR_TEXCOORD0) in vec4 inTexCoord0;
|
||||
layout(location=GPU_ATTR_TANGENT) in vec4 inTangent;
|
||||
layout(location=GPU_ATTR_SKIN_CLUSTER_INDEX) in ivec4 inSkinClusterIndex;
|
||||
layout(location=GPU_ATTR_SKIN_CLUSTER_WEIGHT) in vec4 inSkinClusterWeight;
|
||||
layout(location=GPU_ATTR_TEXCOORD1) in vec4 inTexCoord1;
|
||||
layout(location=GPU_ATTR_TEXCOORD2) in vec4 inTexCoord2;
|
||||
layout(location=GPU_ATTR_TEXCOORD3) in vec4 inTexCoord3;
|
||||
layout(location=GPU_ATTR_TEXCOORD4) in vec4 inTexCoord4;
|
||||
<@endif@>
|
||||
|
|
|
@ -12,6 +12,12 @@
|
|||
#include "Shader.h"
|
||||
#include <math.h>
|
||||
#include <QDebug>
|
||||
#include <set>
|
||||
|
||||
#include <QtCore/QJsonDocument>
|
||||
#include <QtCore/QJsonObject>
|
||||
|
||||
#include <shaders/Shaders.h>
|
||||
|
||||
#include "Context.h"
|
||||
|
||||
|
@ -49,6 +55,14 @@ Shader::~Shader()
|
|||
{
|
||||
}
|
||||
|
||||
void populateSlotSet(Shader::SlotSet& slotSet, const Shader::LocationMap& map) {
|
||||
for (const auto& entry : map) {
|
||||
const auto& name = entry.first;
|
||||
const auto& location = entry.second;
|
||||
slotSet.insert({ name, location, Element() });
|
||||
}
|
||||
}
|
||||
|
||||
Shader::Pointer Shader::createOrReuseDomainShader(Type type, const Source& source) {
|
||||
auto found = _domainShaderMaps[type].find(source);
|
||||
if (found != _domainShaderMaps[type].end()) {
|
||||
|
@ -58,21 +72,32 @@ Shader::Pointer Shader::createOrReuseDomainShader(Type type, const Source& sourc
|
|||
}
|
||||
}
|
||||
auto shader = Pointer(new Shader(type, source));
|
||||
const auto& reflection = source.getReflection();
|
||||
if (0 != reflection.count(BindingType::INPUT)) {
|
||||
populateSlotSet(shader->_inputs, reflection.find(BindingType::INPUT)->second);
|
||||
}
|
||||
if (0 != reflection.count(BindingType::OUTPUT)) {
|
||||
populateSlotSet(shader->_outputs, reflection.find(BindingType::OUTPUT)->second);
|
||||
}
|
||||
if (0 != reflection.count(BindingType::UNIFORM_BUFFER)) {
|
||||
populateSlotSet(shader->_uniformBuffers, reflection.find(BindingType::UNIFORM_BUFFER)->second);
|
||||
}
|
||||
if (0 != reflection.count(BindingType::RESOURCE_BUFFER)) {
|
||||
populateSlotSet(shader->_resourceBuffers, reflection.find(BindingType::RESOURCE_BUFFER)->second);
|
||||
}
|
||||
if (0 != reflection.count(BindingType::TEXTURE)) {
|
||||
populateSlotSet(shader->_textures, reflection.find(BindingType::TEXTURE)->second);
|
||||
}
|
||||
if (0 != reflection.count(BindingType::SAMPLER)) {
|
||||
populateSlotSet(shader->_samplers, reflection.find(BindingType::SAMPLER)->second);
|
||||
}
|
||||
if (0 != reflection.count(BindingType::UNIFORM)) {
|
||||
populateSlotSet(shader->_uniforms, reflection.find(BindingType::UNIFORM)->second);
|
||||
}
|
||||
_domainShaderMaps[type].emplace(source, std::weak_ptr<Shader>(shader));
|
||||
return shader;
|
||||
}
|
||||
|
||||
Shader::Pointer Shader::createVertex(const Source& source) {
|
||||
return createOrReuseDomainShader(VERTEX, source);
|
||||
}
|
||||
|
||||
Shader::Pointer Shader::createPixel(const Source& source) {
|
||||
return createOrReuseDomainShader(PIXEL, source);
|
||||
}
|
||||
|
||||
Shader::Pointer Shader::createGeometry(const Source& source) {
|
||||
return createOrReuseDomainShader(GEOMETRY, source);
|
||||
}
|
||||
|
||||
ShaderPointer Shader::createOrReuseProgramShader(Type type, const Pointer& vertexShader, const Pointer& geometryShader, const Pointer& pixelShader) {
|
||||
PROFILE_RANGE(app, "createOrReuseProgramShader");
|
||||
|
@ -112,36 +137,32 @@ ShaderPointer Shader::createOrReuseProgramShader(Type type, const Pointer& verte
|
|||
|
||||
// Program is a new one, let's create it
|
||||
auto program = Pointer(new Shader(type, vertexShader, geometryShader, pixelShader));
|
||||
|
||||
// Combine the slots from the sub-shaders
|
||||
for (const auto& shader : program->_shaders) {
|
||||
const auto& reflection = shader->_source.getReflection();
|
||||
if (0 != reflection.count(BindingType::UNIFORM_BUFFER)) {
|
||||
populateSlotSet(program->_uniformBuffers, reflection.find(BindingType::UNIFORM_BUFFER)->second);
|
||||
}
|
||||
if (0 != reflection.count(BindingType::RESOURCE_BUFFER)) {
|
||||
populateSlotSet(program->_resourceBuffers, reflection.find(BindingType::RESOURCE_BUFFER)->second);
|
||||
}
|
||||
if (0 != reflection.count(BindingType::TEXTURE)) {
|
||||
populateSlotSet(program->_textures, reflection.find(BindingType::TEXTURE)->second);
|
||||
}
|
||||
if (0 != reflection.count(BindingType::SAMPLER)) {
|
||||
populateSlotSet(program->_samplers, reflection.find(BindingType::SAMPLER)->second);
|
||||
}
|
||||
if (0 != reflection.count(BindingType::UNIFORM)) {
|
||||
populateSlotSet(program->_uniforms, reflection.find(BindingType::UNIFORM)->second);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
_programMap.emplace(key, std::weak_ptr<Shader>(program));
|
||||
return program;
|
||||
}
|
||||
|
||||
|
||||
Shader::Pointer Shader::createProgram(const Pointer& vertexShader, const Pointer& pixelShader) {
|
||||
return createOrReuseProgramShader(PROGRAM, vertexShader, nullptr, pixelShader);
|
||||
}
|
||||
|
||||
Shader::Pointer Shader::createProgram(const Pointer& vertexShader, const Pointer& geometryShader, const Pointer& pixelShader) {
|
||||
return createOrReuseProgramShader(PROGRAM, vertexShader, geometryShader, pixelShader);
|
||||
}
|
||||
|
||||
void Shader::defineSlots(const SlotSet& uniforms, const SlotSet& uniformBuffers, const SlotSet& resourceBuffers, const SlotSet& textures, const SlotSet& samplers, const SlotSet& inputs, const SlotSet& outputs) {
|
||||
_uniforms = uniforms;
|
||||
_uniformBuffers = uniformBuffers;
|
||||
_resourceBuffers = resourceBuffers;
|
||||
_textures = textures;
|
||||
_samplers = samplers;
|
||||
_inputs = inputs;
|
||||
_outputs = outputs;
|
||||
}
|
||||
|
||||
bool Shader::makeProgram(Shader& shader, const Shader::BindingSet& bindings, const CompilationHandler& handler) {
|
||||
if (shader.isProgram()) {
|
||||
return Context::makeProgram(shader, bindings, handler);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void Shader::setCompilationLogs(const CompilationLogs& logs) const {
|
||||
_compilationLogs.clear();
|
||||
for (const auto& log : logs) {
|
||||
|
@ -153,3 +174,124 @@ void Shader::incrementCompilationAttempt() const {
|
|||
_numCompilationAttempts++;
|
||||
}
|
||||
|
||||
Shader::Pointer Shader::createVertex(const Source& source) {
|
||||
return createOrReuseDomainShader(VERTEX, source);
|
||||
}
|
||||
|
||||
Shader::Pointer Shader::createPixel(const Source& source) {
|
||||
return createOrReuseDomainShader(FRAGMENT, source);
|
||||
}
|
||||
|
||||
Shader::Pointer Shader::createVertex(uint32_t id) {
|
||||
return createVertex(getShaderSource(id));
|
||||
}
|
||||
|
||||
Shader::Pointer Shader::createPixel(uint32_t id) {
|
||||
return createPixel(getShaderSource(id));
|
||||
}
|
||||
|
||||
Shader::Pointer Shader::createProgram(const Pointer& vertexShader, const Pointer& pixelShader) {
|
||||
return createOrReuseProgramShader(PROGRAM, vertexShader, nullptr, pixelShader);
|
||||
}
|
||||
|
||||
Shader::Pointer Shader::createProgram(uint32_t programId) {
|
||||
auto vertexShader = createVertex(shader::getVertexId(programId));
|
||||
auto fragmentShader = createPixel(shader::getFragmentId(programId));
|
||||
return createOrReuseProgramShader(PROGRAM, vertexShader, nullptr, fragmentShader);
|
||||
}
|
||||
|
||||
Shader::Pointer Shader::createProgram(const Pointer& vertexShader, const Pointer& geometryShader, const Pointer& pixelShader) {
|
||||
return createOrReuseProgramShader(PROGRAM, vertexShader, geometryShader, pixelShader);
|
||||
}
|
||||
|
||||
static const std::string IGNORED_BINDING = "transformObjectBuffer";
|
||||
|
||||
void updateBindingsFromJsonObject(Shader::LocationMap& inOutSet, const QJsonObject& json) {
|
||||
for (const auto& key : json.keys()) {
|
||||
auto keyStr = key.toStdString();
|
||||
if (IGNORED_BINDING == keyStr) {
|
||||
continue;
|
||||
}
|
||||
inOutSet[keyStr] = json[key].toInt();
|
||||
}
|
||||
}
|
||||
|
||||
void updateTextureAndResourceBuffersFromJsonObjects(Shader::LocationMap& inOutTextures, Shader::LocationMap& inOutResourceBuffers,
|
||||
const QJsonObject& json, const QJsonObject& types) {
|
||||
static const std::string RESOURCE_BUFFER_TEXTURE_TYPE = "samplerBuffer";
|
||||
for (const auto& key : json.keys()) {
|
||||
auto keyStr = key.toStdString();
|
||||
if (keyStr == IGNORED_BINDING) {
|
||||
continue;
|
||||
}
|
||||
auto location = json[key].toInt();
|
||||
auto type = types[key].toString().toStdString();
|
||||
if (type == RESOURCE_BUFFER_TEXTURE_TYPE) {
|
||||
inOutResourceBuffers[keyStr] = location;
|
||||
} else {
|
||||
inOutTextures[key.toStdString()] = location;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Shader::ReflectionMap getShaderReflection(const std::string& reflectionJson) {
|
||||
if (reflectionJson.empty() && reflectionJson != std::string("null")) {
|
||||
return {};
|
||||
}
|
||||
|
||||
#define REFLECT_KEY_INPUTS "inputs"
|
||||
#define REFLECT_KEY_OUTPUTS "outputs"
|
||||
#define REFLECT_KEY_UBOS "uniformBuffers"
|
||||
#define REFLECT_KEY_SSBOS "storageBuffers"
|
||||
#define REFLECT_KEY_UNIFORMS "uniforms"
|
||||
#define REFLECT_KEY_TEXTURES "textures"
|
||||
#define REFLECT_KEY_TEXTURE_TYPES "textureTypes"
|
||||
|
||||
auto doc = QJsonDocument::fromJson(reflectionJson.c_str());
|
||||
if (doc.isNull()) {
|
||||
qWarning() << "Invalid shader reflection JSON" << reflectionJson.c_str();
|
||||
return {};
|
||||
}
|
||||
|
||||
Shader::ReflectionMap result;
|
||||
auto json = doc.object();
|
||||
if (json.contains(REFLECT_KEY_INPUTS)) {
|
||||
updateBindingsFromJsonObject(result[Shader::BindingType::INPUT], json[REFLECT_KEY_INPUTS].toObject());
|
||||
}
|
||||
if (json.contains(REFLECT_KEY_OUTPUTS)) {
|
||||
updateBindingsFromJsonObject(result[Shader::BindingType::OUTPUT], json[REFLECT_KEY_OUTPUTS].toObject());
|
||||
}
|
||||
// FIXME eliminate the last of the uniforms
|
||||
if (json.contains(REFLECT_KEY_UNIFORMS)) {
|
||||
updateBindingsFromJsonObject(result[Shader::BindingType::UNIFORM], json[REFLECT_KEY_UNIFORMS].toObject());
|
||||
}
|
||||
if (json.contains(REFLECT_KEY_UBOS)) {
|
||||
updateBindingsFromJsonObject(result[Shader::BindingType::UNIFORM_BUFFER], json[REFLECT_KEY_UBOS].toObject());
|
||||
}
|
||||
|
||||
// SSBOs need to come BEFORE the textures. In GL 4.5 the reflection slots aren't really used, but in 4.1 the slots
|
||||
// are used to explicitly setup bindings after shader linkage, so we want the resource buffer slots to contain the
|
||||
// texture locations, not the SSBO locations
|
||||
if (json.contains(REFLECT_KEY_SSBOS)) {
|
||||
updateBindingsFromJsonObject(result[Shader::BindingType::RESOURCE_BUFFER], json[REFLECT_KEY_SSBOS].toObject());
|
||||
}
|
||||
|
||||
// samplerBuffer textures map to gpu ResourceBuffer, while all other textures map to regular gpu Texture
|
||||
if (json.contains(REFLECT_KEY_TEXTURES)) {
|
||||
updateTextureAndResourceBuffersFromJsonObjects(
|
||||
result[Shader::BindingType::TEXTURE],
|
||||
result[Shader::BindingType::RESOURCE_BUFFER],
|
||||
json[REFLECT_KEY_TEXTURES].toObject(),
|
||||
json[REFLECT_KEY_TEXTURE_TYPES].toObject());
|
||||
}
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Shader::Source Shader::getShaderSource(uint32_t id) {
|
||||
auto source = shader::loadShaderSource(id);
|
||||
auto reflectionJson = shader::loadShaderReflection(id);
|
||||
auto reflection = getShaderReflection(reflectionJson);
|
||||
return { source, reflection };
|
||||
}
|
||||
|
|
|
@ -15,10 +15,12 @@
|
|||
#include <string>
|
||||
#include <memory>
|
||||
#include <set>
|
||||
#include <unordered_set>
|
||||
#include <unordered_map>
|
||||
#include <map>
|
||||
#include <functional>
|
||||
#include <QUrl>
|
||||
|
||||
|
||||
namespace gpu {
|
||||
|
||||
class Shader {
|
||||
|
@ -26,30 +28,71 @@ public:
|
|||
// unique identifier of a shader
|
||||
using ID = uint32_t;
|
||||
|
||||
typedef std::shared_ptr< Shader > Pointer;
|
||||
typedef std::vector< Pointer > Shaders;
|
||||
enum Type
|
||||
{
|
||||
VERTEX = 0,
|
||||
PIXEL,
|
||||
FRAGMENT = PIXEL,
|
||||
GEOMETRY,
|
||||
NUM_DOMAINS,
|
||||
|
||||
PROGRAM,
|
||||
};
|
||||
|
||||
typedef std::shared_ptr<Shader> Pointer;
|
||||
typedef std::vector<Pointer> Shaders;
|
||||
|
||||
// Needs to match values in shaders/Shaders.h
|
||||
enum class BindingType
|
||||
{
|
||||
INVALID = -1,
|
||||
INPUT = 0,
|
||||
OUTPUT,
|
||||
TEXTURE,
|
||||
SAMPLER,
|
||||
UNIFORM_BUFFER,
|
||||
RESOURCE_BUFFER,
|
||||
UNIFORM,
|
||||
};
|
||||
|
||||
using LocationMap = std::unordered_map<std::string, int32_t>;
|
||||
using ReflectionMap = std::map<BindingType, LocationMap>;
|
||||
|
||||
class Source {
|
||||
public:
|
||||
enum Language {
|
||||
enum Language
|
||||
{
|
||||
INVALID = -1,
|
||||
GLSL = 0,
|
||||
SPIRV = 1,
|
||||
MSL = 2,
|
||||
HLSL = 3,
|
||||
};
|
||||
|
||||
Source() {}
|
||||
Source(const std::string& code, Language lang = GLSL) : _code(code), _lang(lang) {}
|
||||
Source(const Source& source) : _code(source._code), _lang(source._lang) {}
|
||||
Source(const std::string& code, const ReflectionMap& reflection, Language lang = GLSL) :
|
||||
_code(code), _reflection(reflection), _lang(lang) {}
|
||||
Source(const Source& source) : _code(source._code), _reflection(source._reflection), _lang(source._lang) {}
|
||||
virtual ~Source() {}
|
||||
|
||||
|
||||
virtual const std::string& getCode() const { return _code; }
|
||||
virtual const ReflectionMap& getReflection() const { return _reflection; }
|
||||
|
||||
class Less {
|
||||
public:
|
||||
bool operator() (const Source& x, const Source& y) const { if (x._lang == y._lang) { return x._code < y._code; } else { return (x._lang < y._lang); } }
|
||||
bool operator()(const Source& x, const Source& y) const {
|
||||
if (x._lang == y._lang) {
|
||||
return x._code < y._code;
|
||||
} else {
|
||||
return (x._lang < y._lang);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
protected:
|
||||
std::string _code;
|
||||
Language _lang = GLSL;
|
||||
ReflectionMap _reflection;
|
||||
Language _lang;
|
||||
};
|
||||
|
||||
struct CompilationLog {
|
||||
|
@ -57,30 +100,40 @@ public:
|
|||
bool compiled{ false };
|
||||
|
||||
CompilationLog() {}
|
||||
CompilationLog(const CompilationLog& src) :
|
||||
message(src.message),
|
||||
compiled(src.compiled) {}
|
||||
CompilationLog(const CompilationLog& src) : message(src.message), compiled(src.compiled) {}
|
||||
};
|
||||
using CompilationLogs = std::vector<CompilationLog>;
|
||||
|
||||
static const int32 INVALID_LOCATION = -1;
|
||||
|
||||
template <typename T>
|
||||
class Less {
|
||||
public:
|
||||
bool operator()(const T& x, const T& y) const { return x._name < y._name; }
|
||||
};
|
||||
|
||||
class Slot {
|
||||
public:
|
||||
|
||||
std::string _name;
|
||||
int32 _location{INVALID_LOCATION};
|
||||
int32 _location{ INVALID_LOCATION };
|
||||
Element _element;
|
||||
uint16 _resourceType{Resource::BUFFER};
|
||||
uint32 _size { 0 };
|
||||
|
||||
Slot(const Slot& s) : _name(s._name), _location(s._location), _element(s._element), _resourceType(s._resourceType), _size(s._size) {}
|
||||
Slot(Slot&& s) : _name(s._name), _location(s._location), _element(s._element), _resourceType(s._resourceType), _size(s._size) {}
|
||||
Slot(const std::string& name, int32 location, const Element& element, uint16 resourceType = Resource::BUFFER, uint32 size = 0) :
|
||||
_name(name), _location(location), _element(element), _resourceType(resourceType), _size(size) {}
|
||||
uint16 _resourceType{ Resource::BUFFER };
|
||||
uint32 _size{ 0 };
|
||||
|
||||
Slot(const Slot& s) :
|
||||
_name(s._name), _location(s._location), _element(s._element), _resourceType(s._resourceType), _size(s._size) {}
|
||||
Slot(Slot&& s) :
|
||||
_name(s._name), _location(s._location), _element(s._element), _resourceType(s._resourceType), _size(s._size) {}
|
||||
Slot(const std::string& name,
|
||||
int32 location,
|
||||
const Element& element,
|
||||
uint16 resourceType = Resource::BUFFER,
|
||||
uint32 size = 0) :
|
||||
_name(name),
|
||||
_location(location), _element(element), _resourceType(resourceType), _size(size) {}
|
||||
Slot(const std::string& name) : _name(name) {}
|
||||
|
||||
Slot& operator= (const Slot& s) {
|
||||
Slot& operator=(const Slot& s) {
|
||||
_name = s._name;
|
||||
_location = s._location;
|
||||
_element = s._element;
|
||||
|
@ -90,54 +143,62 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
class Binding {
|
||||
public:
|
||||
std::string _name;
|
||||
int32 _location;
|
||||
Binding(const std::string& name, int32 loc = INVALID_LOCATION) : _name(name), _location(loc) {}
|
||||
};
|
||||
class SlotSet : protected std::set<Slot, Less<Slot>> {
|
||||
using Parent = std::set<Slot, Less<Slot>>;
|
||||
|
||||
template <typename T> class Less {
|
||||
public:
|
||||
bool operator() (const T& x, const T& y) const { return x._name < y._name; }
|
||||
};
|
||||
|
||||
class SlotSet : public std::set<Slot, Less<Slot>> {
|
||||
public:
|
||||
Slot findSlot(const std::string& name) const {
|
||||
auto key = Slot(name);
|
||||
auto found = static_cast<const std::set<Slot, Less<Slot>>*>(this)->find(key);
|
||||
if (found != end()) {
|
||||
return (*found);
|
||||
void insert(const Parent::value_type& value) {
|
||||
Parent::insert(value);
|
||||
if (value._location != INVALID_LOCATION) {
|
||||
_validSlots.insert(value._location);
|
||||
}
|
||||
return key;
|
||||
}
|
||||
int32 findLocation(const std::string& name) const {
|
||||
return findSlot(name)._location;
|
||||
|
||||
using Parent::begin;
|
||||
using Parent::empty;
|
||||
using Parent::end;
|
||||
using Parent::size;
|
||||
|
||||
using LocationMap = std::unordered_map<std::string, int32>;
|
||||
using NameVector = std::vector<std::string>;
|
||||
|
||||
NameVector getNames() const {
|
||||
NameVector result;
|
||||
for (const auto& entry : *this) {
|
||||
result.push_back(entry._name);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
LocationMap getLocationsByName() const {
|
||||
LocationMap result;
|
||||
for (const auto& entry : *this) {
|
||||
result.insert({ entry._name, entry._location });
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
bool isValid(int32 slot) const { return 0 != _validSlots.count(slot); }
|
||||
|
||||
protected:
|
||||
std::unordered_set<int> _validSlots;
|
||||
};
|
||||
|
||||
typedef std::set<Binding, Less<Binding>> BindingSet;
|
||||
|
||||
|
||||
enum Type {
|
||||
VERTEX = 0,
|
||||
PIXEL,
|
||||
GEOMETRY,
|
||||
NUM_DOMAINS,
|
||||
|
||||
PROGRAM,
|
||||
};
|
||||
static Source getShaderSource(uint32_t id);
|
||||
static Source getVertexShaderSource(uint32_t id) { return getShaderSource(id); }
|
||||
static Source getFragmentShaderSource(uint32_t id) { return getShaderSource(id); }
|
||||
|
||||
static Pointer createVertex(const Source& source);
|
||||
static Pointer createPixel(const Source& source);
|
||||
static Pointer createGeometry(const Source& source);
|
||||
static Pointer createVertex(uint32_t shaderId);
|
||||
static Pointer createPixel(uint32_t shaderId);
|
||||
static Pointer createGeometry(uint32_t shaderId);
|
||||
|
||||
static Pointer createProgram(uint32_t programId);
|
||||
static Pointer createProgram(const Pointer& vertexShader, const Pointer& pixelShader);
|
||||
static Pointer createProgram(const Pointer& vertexShader, const Pointer& geometryShader, const Pointer& pixelShader);
|
||||
|
||||
|
||||
~Shader();
|
||||
|
||||
ID getID() const { return _ID; }
|
||||
|
@ -156,22 +217,6 @@ public:
|
|||
const SlotSet& getResourceBuffers() const { return _resourceBuffers; }
|
||||
const SlotSet& getTextures() const { return _textures; }
|
||||
const SlotSet& getSamplers() const { return _samplers; }
|
||||
|
||||
const SlotSet& getInputs() const { return _inputs; }
|
||||
const SlotSet& getOutputs() const { return _outputs; }
|
||||
|
||||
// Define the list of uniforms, inputs and outputs for the shader
|
||||
// This call is intendend to build the list of exposed slots in order
|
||||
// to correctly bind resource to the shader.
|
||||
// These can be build "manually" from knowledge of the atual shader code
|
||||
// or automatically by calling "makeShader()", this is the preferred way
|
||||
void defineSlots(const SlotSet& uniforms,
|
||||
const SlotSet& uniformBuffers,
|
||||
const SlotSet& resourceBuffers,
|
||||
const SlotSet& textures,
|
||||
const SlotSet& samplers,
|
||||
const SlotSet& inputs,
|
||||
const SlotSet& outputs);
|
||||
|
||||
// Compilation Handler can be passed while compiling a shader (in the makeProgram call) to be able to give the hand to
|
||||
// the caller thread if the comilation fails and to prvide a different version of the source for it
|
||||
|
@ -180,22 +225,7 @@ public:
|
|||
// @param2 the compilation log containing the error message
|
||||
// @param3 a new string ready to be filled with the new version of the source that could be proposed from the handler functor
|
||||
// @return boolean true if the backend should keep trying to compile the shader with the new source returned or false to stop and fail that shader compilation
|
||||
using CompilationHandler = std::function<bool (const Shader&, const std::string&, CompilationLog&, std::string&)>;
|
||||
|
||||
// makeProgram(...) make a program shader ready to be used in a Batch.
|
||||
// It compiles the sub shaders, link them and defines the Slots and their bindings.
|
||||
// If the shader passed is not a program, nothing happens.
|
||||
//
|
||||
// It is possible to provide a set of slot bindings (from the name of the slot to a unit number) allowing
|
||||
// to make sure slots with the same semantics can be always bound on the same location from shader to shader.
|
||||
// For example, the "diffuseMap" can always be bound to texture unit #1 for different shaders by specifying a Binding("diffuseMap", 1)
|
||||
//
|
||||
// As of now (03/2015), the call to makeProgram is in fact calling gpu::Context::makeProgram and does rely
|
||||
// on the underneath gpu::Context::Backend available. Since we only support glsl, this means that it relies
|
||||
// on a gl Context and the driver to compile the glsl shader.
|
||||
// Hoppefully in a few years the shader compilation will be completely abstracted in a separate shader compiler library
|
||||
// independant of the graphics api in use underneath (looking at you opengl & vulkan).
|
||||
static bool makeProgram(Shader& shader, const Shader::BindingSet& bindings = Shader::BindingSet(), const CompilationHandler& handler = nullptr);
|
||||
using CompilationHandler = std::function<bool(const Shader&, const std::string&, CompilationLog&, std::string&)>;
|
||||
|
||||
// Check the compilation state
|
||||
bool compilationHasFailed() const { return _compilationHasFailed; }
|
||||
|
@ -207,16 +237,14 @@ public:
|
|||
void setCompilationLogs(const CompilationLogs& logs) const;
|
||||
void incrementCompilationAttempt() const;
|
||||
|
||||
|
||||
const GPUObjectPointer gpuObject {};
|
||||
const GPUObjectPointer gpuObject{};
|
||||
|
||||
protected:
|
||||
Shader(Type type, const Source& source);
|
||||
Shader(Type type, const Pointer& vertex, const Pointer& geometry, const Pointer& pixel);
|
||||
|
||||
Shader(const Shader& shader); // deep copy of the sysmem shader
|
||||
Shader& operator=(const Shader& shader); // deep copy of the sysmem texture
|
||||
|
||||
Shader(const Shader& shader); // deep copy of the sysmem shader
|
||||
Shader& operator=(const Shader& shader); // deep copy of the sysmem texture
|
||||
|
||||
// Source contains the actual source code or nothing if the shader is a program
|
||||
Source _source;
|
||||
|
@ -245,32 +273,29 @@ protected:
|
|||
mutable CompilationLogs _compilationLogs;
|
||||
|
||||
// Whether or not the shader compilation failed
|
||||
bool _compilationHasFailed { false };
|
||||
bool _compilationHasFailed{ false };
|
||||
|
||||
|
||||
// Global maps of the shaders
|
||||
// Global maps of the shaders
|
||||
// Unique shader ID
|
||||
static std::atomic<ID> _nextShaderID;
|
||||
|
||||
using ShaderMap = std::map<Source, std::weak_ptr<Shader>, Source::Less>;
|
||||
using ShaderMap = std::map<Source, std::weak_ptr<Shader>, Source::Less>;
|
||||
using DomainShaderMaps = std::array<ShaderMap, NUM_DOMAINS>;
|
||||
static DomainShaderMaps _domainShaderMaps;
|
||||
|
||||
static ShaderPointer createOrReuseDomainShader(Type type, const Source& source);
|
||||
|
||||
using ProgramMapKey = glm::uvec3; // The IDs of the shaders in a program make its key
|
||||
using ProgramMapKey = glm::uvec3; // The IDs of the shaders in a program make its key
|
||||
class ProgramKeyLess {
|
||||
public:
|
||||
bool operator() (const ProgramMapKey& l, const ProgramMapKey& r) const {
|
||||
bool operator()(const ProgramMapKey& l, const ProgramMapKey& r) const {
|
||||
if (l.x == r.x) {
|
||||
if (l.y == r.y) {
|
||||
return (l.z < r.z);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
return (l.y < r.y);
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
return (l.x < r.x);
|
||||
}
|
||||
}
|
||||
|
@ -278,13 +303,15 @@ protected:
|
|||
using ProgramMap = std::map<ProgramMapKey, std::weak_ptr<Shader>, ProgramKeyLess>;
|
||||
static ProgramMap _programMap;
|
||||
|
||||
static ShaderPointer createOrReuseProgramShader(Type type, const Pointer& vertexShader, const Pointer& geometryShader, const Pointer& pixelShader);
|
||||
static ShaderPointer createOrReuseProgramShader(Type type,
|
||||
const Pointer& vertexShader,
|
||||
const Pointer& geometryShader,
|
||||
const Pointer& pixelShader);
|
||||
};
|
||||
|
||||
typedef Shader::Pointer ShaderPointer;
|
||||
typedef std::vector< ShaderPointer > Shaders;
|
||||
|
||||
};
|
||||
typedef std::vector<ShaderPointer> Shaders;
|
||||
|
||||
}; // namespace gpu
|
||||
|
||||
#endif
|
||||
|
|
129
libraries/gpu/src/gpu/ShaderConstants.h
Normal file
129
libraries/gpu/src/gpu/ShaderConstants.h
Normal file
|
@ -0,0 +1,129 @@
|
|||
// <!
|
||||
// Created by Bradley Austin Davis on 2018/05/25
|
||||
// Copyright 2013-2018 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
// !>
|
||||
|
||||
// <@if not GPU_SHADER_CONSTANTS_H@>
|
||||
// <@def GPU_SHADER_CONSTANTS_H@>
|
||||
|
||||
// Hack comment to absorb the extra '//' scribe prepends
|
||||
|
||||
#ifndef GPU_SHADER_CONSTANTS_H
|
||||
#define GPU_SHADER_CONSTANTS_H
|
||||
|
||||
#define GPU_BUFFER_TRANSFORM_CAMERA 15
|
||||
#define GPU_BUFFER_TEXTURE_TABLE0 16
|
||||
#define GPU_BUFFER_TEXTURE_TABLE1 17
|
||||
#define GPU_BUFFER_CAMERA_CORRECTION 18
|
||||
|
||||
#define GPU_TEXTURE_TRANSFORM_OBJECT 31
|
||||
|
||||
#define GPU_STORAGE_TRANSFORM_OBJECT 7
|
||||
|
||||
#define GPU_ATTR_POSITION 0
|
||||
#define GPU_ATTR_NORMAL 1
|
||||
#define GPU_ATTR_COLOR 2
|
||||
#define GPU_ATTR_TEXCOORD0 3
|
||||
#define GPU_ATTR_TANGENT 4
|
||||
#define GPU_ATTR_SKIN_CLUSTER_INDEX 5
|
||||
#define GPU_ATTR_SKIN_CLUSTER_WEIGHT 6
|
||||
#define GPU_ATTR_TEXCOORD1 7
|
||||
#define GPU_ATTR_TEXCOORD2 8
|
||||
#define GPU_ATTR_TEXCOORD3 9
|
||||
#define GPU_ATTR_TEXCOORD4 10
|
||||
#define GPU_ATTR_STEREO_SIDE 14
|
||||
#define GPU_ATTR_DRAW_CALL_INFO 15
|
||||
|
||||
// OSX seems to have an issue using 14 as an attribute location for passing from the vertex to the fragment shader
|
||||
#define GPU_ATTR_V2F_STEREO_SIDE 8
|
||||
|
||||
#define GPU_UNIFORM_COLOR 101
|
||||
#define GPU_UNIFORM_TEXCOORD_RECT 102
|
||||
#define GPU_UNIFORM_EXTRA0 110
|
||||
#define GPU_UNIFORM_EXTRA1 111
|
||||
#define GPU_UNIFORM_EXTRA2 112
|
||||
#define GPU_UNIFORM_EXTRA3 113
|
||||
#define GPU_UNIFORM_EXTRA4 114
|
||||
#define GPU_UNIFORM_EXTRA5 115
|
||||
#define GPU_UNIFORM_EXTRA6 116
|
||||
#define GPU_UNIFORM_EXTRA7 117
|
||||
#define GPU_UNIFORM_EXTRA8 118
|
||||
#define GPU_UNIFORM_EXTRA9 119
|
||||
|
||||
// <!
|
||||
|
||||
namespace gpu { namespace slot {
|
||||
|
||||
namespace buffer {
|
||||
enum Buffer {
|
||||
CameraTransform = GPU_BUFFER_TRANSFORM_CAMERA,
|
||||
TextureTable0 = GPU_BUFFER_TEXTURE_TABLE0,
|
||||
TextureTable1 = GPU_BUFFER_TEXTURE_TABLE1,
|
||||
CameraCorrection = GPU_BUFFER_CAMERA_CORRECTION,
|
||||
};
|
||||
} // namespace buffer
|
||||
|
||||
namespace texture {
|
||||
enum Texture {
|
||||
ObjectTransforms = GPU_TEXTURE_TRANSFORM_OBJECT,
|
||||
};
|
||||
} // namespace texture
|
||||
|
||||
namespace storage {
|
||||
enum Storage {
|
||||
ObjectTransforms = GPU_STORAGE_TRANSFORM_OBJECT,
|
||||
};
|
||||
} // namespace storage
|
||||
|
||||
namespace attr {
|
||||
enum Attribute {
|
||||
Position = GPU_ATTR_POSITION,
|
||||
Normal = GPU_ATTR_NORMAL,
|
||||
Color = GPU_ATTR_COLOR,
|
||||
TexCoord0 = GPU_ATTR_TEXCOORD0,
|
||||
Tangent = GPU_ATTR_TANGENT,
|
||||
SkinClusterIndex = GPU_ATTR_SKIN_CLUSTER_INDEX,
|
||||
SkinClusterWeight = GPU_ATTR_SKIN_CLUSTER_WEIGHT,
|
||||
TexCoord1 = GPU_ATTR_TEXCOORD1,
|
||||
TexCoord2 = GPU_ATTR_TEXCOORD2,
|
||||
TexCoord3 = GPU_ATTR_TEXCOORD3,
|
||||
TexCoord4 = GPU_ATTR_TEXCOORD4,
|
||||
StereoSide = GPU_ATTR_STEREO_SIDE,
|
||||
DrawCallInfo = GPU_ATTR_DRAW_CALL_INFO,
|
||||
};
|
||||
} // namespace attr
|
||||
|
||||
namespace uniform {
|
||||
enum Uniform {
|
||||
Color = GPU_UNIFORM_COLOR,
|
||||
TexCoordRect = GPU_UNIFORM_TEXCOORD_RECT,
|
||||
Extra0 = GPU_UNIFORM_EXTRA0,
|
||||
Extra1 = GPU_UNIFORM_EXTRA1,
|
||||
Extra2 = GPU_UNIFORM_EXTRA2,
|
||||
Extra3 = GPU_UNIFORM_EXTRA3,
|
||||
Extra4 = GPU_UNIFORM_EXTRA4,
|
||||
Extra5 = GPU_UNIFORM_EXTRA5,
|
||||
Extra6 = GPU_UNIFORM_EXTRA6,
|
||||
Extra7 = GPU_UNIFORM_EXTRA7,
|
||||
Extra8 = GPU_UNIFORM_EXTRA8,
|
||||
Extra9 = GPU_UNIFORM_EXTRA9,
|
||||
};
|
||||
} // namespace uniform
|
||||
|
||||
} } // namespace gpu::slot
|
||||
|
||||
// !>
|
||||
|
||||
// Hack Comment
|
||||
#endif // GPU_SHADER_CONSTANTS_H
|
||||
|
||||
// <@if 1@>
|
||||
// Trigger Scribe include
|
||||
// <@endif@> <!def that !>
|
||||
|
||||
// <@endif@>
|
||||
|
||||
// Hack Comment
|
|
@ -1,163 +0,0 @@
|
|||
//
|
||||
// StandardShaderLib.cpp
|
||||
// libraries/gpu/src/gpu
|
||||
//
|
||||
// Collection of standard shaders that can be used all over the place
|
||||
//
|
||||
// Created by Sam Gateau on 6/22/2015.
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
#include "StandardShaderLib.h"
|
||||
|
||||
#include "DrawUnitQuadTexcoord_vert.h"
|
||||
#include "DrawTransformUnitQuad_vert.h"
|
||||
#include "DrawTexcoordRectTransformUnitQuad_vert.h"
|
||||
#include "DrawViewportQuadTransformTexcoord_vert.h"
|
||||
#include "DrawVertexPosition_vert.h"
|
||||
#include "DrawTransformVertexPosition_vert.h"
|
||||
|
||||
const char DrawNada_frag[] = "void main(void) {}"; // DrawNada is really simple...
|
||||
|
||||
#include "DrawWhite_frag.h"
|
||||
#include "DrawColor_frag.h"
|
||||
#include "DrawTexture_frag.h"
|
||||
#include "DrawTextureMirroredX_frag.h"
|
||||
#include "DrawTextureOpaque_frag.h"
|
||||
#include "DrawColoredTexture_frag.h"
|
||||
|
||||
using namespace gpu;
|
||||
|
||||
ShaderPointer StandardShaderLib::_drawUnitQuadTexcoordVS;
|
||||
ShaderPointer StandardShaderLib::_drawTransformUnitQuadVS;
|
||||
ShaderPointer StandardShaderLib::_drawTexcoordRectTransformUnitQuadVS;
|
||||
ShaderPointer StandardShaderLib::_drawViewportQuadTransformTexcoordVS;
|
||||
ShaderPointer StandardShaderLib::_drawVertexPositionVS;
|
||||
ShaderPointer StandardShaderLib::_drawTransformVertexPositionVS;
|
||||
ShaderPointer StandardShaderLib::_drawNadaPS;
|
||||
ShaderPointer StandardShaderLib::_drawWhitePS;
|
||||
ShaderPointer StandardShaderLib::_drawColorPS;
|
||||
ShaderPointer StandardShaderLib::_drawTexturePS;
|
||||
ShaderPointer StandardShaderLib::_drawTextureMirroredXPS;
|
||||
ShaderPointer StandardShaderLib::_drawTextureOpaquePS;
|
||||
ShaderPointer StandardShaderLib::_drawColoredTexturePS;
|
||||
StandardShaderLib::ProgramMap StandardShaderLib::_programs;
|
||||
|
||||
ShaderPointer StandardShaderLib::getProgram(GetShader getVS, GetShader getPS) {
|
||||
|
||||
auto programIt = _programs.find(std::pair<GetShader, GetShader>(getVS, getPS));
|
||||
if (programIt != _programs.end()) {
|
||||
return (*programIt).second;
|
||||
} else {
|
||||
auto vs = (getVS)();
|
||||
auto ps = (getPS)();
|
||||
auto program = gpu::Shader::createProgram(vs, ps);
|
||||
if (program) {
|
||||
// Program created, let's try to make it
|
||||
if (gpu::Shader::makeProgram((*program))) {
|
||||
// All good, backup and return that program
|
||||
_programs.insert(ProgramMap::value_type(std::pair<GetShader, GetShader>(getVS, getPS), program));
|
||||
return program;
|
||||
} else {
|
||||
// Failed to make the program probably because vs and ps cannot work together?
|
||||
}
|
||||
} else {
|
||||
// Failed to create the program maybe because ps and vs are not true vertex and pixel shaders?
|
||||
}
|
||||
}
|
||||
return ShaderPointer();
|
||||
}
|
||||
|
||||
|
||||
ShaderPointer StandardShaderLib::getDrawUnitQuadTexcoordVS() {
|
||||
if (!_drawUnitQuadTexcoordVS) {
|
||||
_drawUnitQuadTexcoordVS = DrawUnitQuadTexcoord_vert::getShader();
|
||||
}
|
||||
return _drawUnitQuadTexcoordVS;
|
||||
}
|
||||
|
||||
ShaderPointer StandardShaderLib::getDrawTransformUnitQuadVS() {
|
||||
if (!_drawTransformUnitQuadVS) {
|
||||
_drawTransformUnitQuadVS = DrawTransformUnitQuad_vert::getShader();
|
||||
}
|
||||
return _drawTransformUnitQuadVS;
|
||||
}
|
||||
|
||||
ShaderPointer StandardShaderLib::getDrawTexcoordRectTransformUnitQuadVS() {
|
||||
if (!_drawTexcoordRectTransformUnitQuadVS) {
|
||||
_drawTexcoordRectTransformUnitQuadVS = DrawTexcoordRectTransformUnitQuad_vert::getShader();
|
||||
}
|
||||
return _drawTexcoordRectTransformUnitQuadVS;
|
||||
}
|
||||
|
||||
ShaderPointer StandardShaderLib::getDrawViewportQuadTransformTexcoordVS() {
|
||||
if (!_drawViewportQuadTransformTexcoordVS) {
|
||||
_drawViewportQuadTransformTexcoordVS = DrawViewportQuadTransformTexcoord_vert::getShader();
|
||||
}
|
||||
return _drawViewportQuadTransformTexcoordVS;
|
||||
}
|
||||
|
||||
ShaderPointer StandardShaderLib::getDrawVertexPositionVS() {
|
||||
if (!_drawVertexPositionVS) {
|
||||
_drawVertexPositionVS = DrawVertexPosition_vert::getShader();
|
||||
}
|
||||
return _drawVertexPositionVS;
|
||||
}
|
||||
|
||||
ShaderPointer StandardShaderLib::getDrawTransformVertexPositionVS() {
|
||||
if (!_drawTransformVertexPositionVS) {
|
||||
_drawTransformVertexPositionVS = DrawTransformVertexPosition_vert::getShader();
|
||||
}
|
||||
return _drawTransformVertexPositionVS;
|
||||
}
|
||||
|
||||
ShaderPointer StandardShaderLib::getDrawNadaPS() {
|
||||
if (!_drawNadaPS) {
|
||||
_drawNadaPS = gpu::Shader::createPixel(std::string(DrawNada_frag));
|
||||
}
|
||||
return _drawNadaPS;
|
||||
}
|
||||
|
||||
ShaderPointer StandardShaderLib::getDrawWhitePS() {
|
||||
if (!_drawWhitePS) {
|
||||
_drawWhitePS = DrawWhite_frag::getShader();
|
||||
}
|
||||
return _drawWhitePS;
|
||||
}
|
||||
|
||||
ShaderPointer StandardShaderLib::getDrawColorPS() {
|
||||
if (!_drawColorPS) {
|
||||
_drawColorPS = DrawColor_frag::getShader();
|
||||
}
|
||||
return _drawColorPS;
|
||||
}
|
||||
|
||||
ShaderPointer StandardShaderLib::getDrawTexturePS() {
|
||||
if (!_drawTexturePS) {
|
||||
_drawTexturePS = DrawTexture_frag::getShader();
|
||||
}
|
||||
return _drawTexturePS;
|
||||
}
|
||||
|
||||
ShaderPointer StandardShaderLib::getDrawTextureMirroredXPS() {
|
||||
if (!_drawTextureMirroredXPS) {
|
||||
_drawTextureMirroredXPS = DrawTextureMirroredX_frag::getShader();
|
||||
}
|
||||
return _drawTextureMirroredXPS;
|
||||
}
|
||||
|
||||
ShaderPointer StandardShaderLib::getDrawTextureOpaquePS() {
|
||||
if (!_drawTextureOpaquePS) {
|
||||
_drawTextureOpaquePS = DrawTextureOpaque_frag::getShader();
|
||||
}
|
||||
return _drawTextureOpaquePS;
|
||||
}
|
||||
|
||||
ShaderPointer StandardShaderLib::getDrawColoredTexturePS() {
|
||||
if (!_drawColoredTexturePS) {
|
||||
_drawColoredTexturePS = DrawColoredTexture_frag::getShader();
|
||||
}
|
||||
return _drawColoredTexturePS;
|
||||
}
|
|
@ -1,84 +0,0 @@
|
|||
//
|
||||
// StandardShaderLib.h
|
||||
// libraries/gpu/src/gpu
|
||||
//
|
||||
// Collection of standard shaders that can be used all over the place
|
||||
//
|
||||
// Created by Sam Gateau on 6/22/2015.
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
#ifndef hifi_gpu_StandardShaderLib_h
|
||||
#define hifi_gpu_StandardShaderLib_h
|
||||
|
||||
#include <assert.h>
|
||||
#include <map>
|
||||
|
||||
#include "Shader.h"
|
||||
|
||||
namespace gpu {
|
||||
|
||||
class StandardShaderLib {
|
||||
public:
|
||||
|
||||
// Shader draws the unit quad in the full viewport clipPos = ([(-1,-1),(1,1)]) and the unit texcoord = [(0,0),(1,1)].
|
||||
static ShaderPointer getDrawUnitQuadTexcoordVS();
|
||||
|
||||
// Shader draw the unit quad objectPos = ([(-1,-1),(1,1)]) and transform it by the full model transform stack (Model, View, Proj).
|
||||
// A texcoord attribute is also generated texcoord = [(0,0),(1,1)]
|
||||
static ShaderPointer getDrawTransformUnitQuadVS();
|
||||
|
||||
// Shader draw the unit quad objectPos = ([(-1,-1),(1,1)]) and transform it by the full model transform stack (Model, View, Proj).
|
||||
// A texcoord attribute is also generated covering a rect defined from the uniform vec4 texcoordRect: texcoord = [texcoordRect.xy,texcoordRect.xy + texcoordRect.zw]
|
||||
static ShaderPointer getDrawTexcoordRectTransformUnitQuadVS();
|
||||
|
||||
// Shader draws the unit quad in the full viewport clipPos = ([(-1,-1),(1,1)]) and transform the texcoord = [(0,0),(1,1)] by the model transform.
|
||||
static ShaderPointer getDrawViewportQuadTransformTexcoordVS();
|
||||
|
||||
// Shader draw the fed vertex position and transform it by the full model transform stack (Model, View, Proj).
|
||||
// simply output the world pos and the clip pos to the next stage
|
||||
static ShaderPointer getDrawVertexPositionVS();
|
||||
static ShaderPointer getDrawTransformVertexPositionVS();
|
||||
|
||||
// PShader does nothing, no really nothing, but still needed for defining a program triggering rasterization
|
||||
static ShaderPointer getDrawNadaPS();
|
||||
|
||||
static ShaderPointer getDrawWhitePS();
|
||||
static ShaderPointer getDrawColorPS();
|
||||
static ShaderPointer getDrawTexturePS();
|
||||
static ShaderPointer getDrawTextureMirroredXPS();
|
||||
static ShaderPointer getDrawTextureOpaquePS();
|
||||
static ShaderPointer getDrawColoredTexturePS();
|
||||
|
||||
// The shader program combining the shaders available above, so they are unique
|
||||
typedef ShaderPointer (*GetShader) ();
|
||||
static ShaderPointer getProgram(GetShader vs, GetShader ps);
|
||||
|
||||
protected:
|
||||
|
||||
static ShaderPointer _drawUnitQuadTexcoordVS;
|
||||
static ShaderPointer _drawTransformUnitQuadVS;
|
||||
static ShaderPointer _drawTexcoordRectTransformUnitQuadVS;
|
||||
static ShaderPointer _drawViewportQuadTransformTexcoordVS;
|
||||
|
||||
static ShaderPointer _drawVertexPositionVS;
|
||||
static ShaderPointer _drawTransformVertexPositionVS;
|
||||
|
||||
static ShaderPointer _drawNadaPS;
|
||||
static ShaderPointer _drawWhitePS;
|
||||
static ShaderPointer _drawColorPS;
|
||||
static ShaderPointer _drawTexturePS;
|
||||
static ShaderPointer _drawTextureMirroredXPS;
|
||||
static ShaderPointer _drawTextureOpaquePS;
|
||||
static ShaderPointer _drawColoredTexturePS;
|
||||
|
||||
typedef std::map<std::pair<GetShader, GetShader>, ShaderPointer> ProgramMap;
|
||||
static ProgramMap _programs;
|
||||
};
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif
|
|
@ -22,8 +22,7 @@ struct GPUTextureTable {
|
|||
#define tableTex(name, slot) sampler2D(name._textures[slot].xy)
|
||||
#define tableTexMinLod(name, slot) float(name._textures[slot].z)
|
||||
|
||||
#define tableTexValue(name, slot, uv) \
|
||||
tableTexValueLod(tableTex(matTex, albedoMap), tableTexMinLod(matTex, albedoMap), uv)
|
||||
#define tableTexValue(name, slot, uv) tableTexValueLod(tableTex(matTex, albedoMap), tableTexMinLod(matTex, albedoMap), uv)
|
||||
|
||||
vec4 tableTexValueLod(sampler2D sampler, float minLod, vec2 uv) {
|
||||
float queryLod = textureQueryLod(sampler, uv).x;
|
||||
|
|
|
@ -10,12 +10,13 @@
|
|||
<@if not GPU_TRANSFORM_STATE_SLH@>
|
||||
<@def GPU_TRANSFORM_STATE_SLH@>
|
||||
|
||||
<@include gpu/ShaderConstants.h@>
|
||||
<@func declareStandardCameraTransform()@>
|
||||
<@include gpu/TransformCamera_shared.slh@>
|
||||
|
||||
#define TransformCamera _TransformCamera
|
||||
|
||||
layout(std140) uniform transformCameraBuffer {
|
||||
layout(std140, binding=GPU_BUFFER_TRANSFORM_CAMERA) uniform transformCameraBuffer {
|
||||
#ifdef GPU_TRANSFORM_IS_STEREO
|
||||
#ifdef GPU_TRANSFORM_STEREO_CAMERA
|
||||
TransformCamera _camera[2];
|
||||
|
@ -31,10 +32,10 @@ layout(std140) uniform transformCameraBuffer {
|
|||
#ifdef GPU_TRANSFORM_IS_STEREO
|
||||
#ifdef GPU_TRANSFORM_STEREO_CAMERA
|
||||
#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED
|
||||
layout(location=14) in int _inStereoSide;
|
||||
layout(location=GPU_ATTR_STEREO_SIDE) in int _inStereoSide;
|
||||
#endif
|
||||
|
||||
flat out int _stereoSide;
|
||||
layout(location=GPU_ATTR_V2F_STEREO_SIDE) flat out int _stereoSide;
|
||||
|
||||
// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2
|
||||
int gpu_InstanceID() {
|
||||
|
@ -59,7 +60,7 @@ int gpu_InstanceID() {
|
|||
|
||||
#ifdef GPU_PIXEL_SHADER
|
||||
#ifdef GPU_TRANSFORM_STEREO_CAMERA
|
||||
flat in int _stereoSide;
|
||||
layout(location=GPU_ATTR_V2F_STEREO_SIDE) flat in int _stereoSide;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
@ -116,10 +117,10 @@ struct TransformObject {
|
|||
mat4 _modelInverse;
|
||||
};
|
||||
|
||||
layout(location=15) in ivec2 _drawCallInfo;
|
||||
layout(location=GPU_ATTR_DRAW_CALL_INFO) in ivec2 _drawCallInfo;
|
||||
|
||||
#if defined(GPU_SSBO_TRANSFORM_OBJECT)
|
||||
layout(std140) buffer transformObjectBuffer {
|
||||
layout(std140, binding=GPU_STORAGE_TRANSFORM_OBJECT) buffer transformObjectBuffer {
|
||||
TransformObject _object[];
|
||||
};
|
||||
TransformObject getTransformObject() {
|
||||
|
@ -127,7 +128,7 @@ TransformObject getTransformObject() {
|
|||
return transformObject;
|
||||
}
|
||||
#else
|
||||
uniform samplerBuffer transformObjectBuffer;
|
||||
layout(binding=GPU_TEXTURE_TRANSFORM_OBJECT) uniform samplerBuffer transformObjectBuffer;
|
||||
|
||||
TransformObject getTransformObject() {
|
||||
int offset = 8 * _drawCallInfo.x;
|
||||
|
|
|
@ -28,7 +28,6 @@ class Backend : public gpu::Backend {
|
|||
friend class gpu::Context;
|
||||
static void init() {}
|
||||
static gpu::Backend* createBackend() { return new Backend(); }
|
||||
static bool makeProgram(Shader& shader, const Shader::BindingSet& slotBindings, const Shader::CompilationHandler& handler) { return true; }
|
||||
|
||||
protected:
|
||||
explicit Backend(bool syncCache) : Parent() { }
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
set(TARGET_NAME graphics)
|
||||
AUTOSCRIBE_SHADER_LIB(gpu graphics)
|
||||
setup_hifi_library()
|
||||
link_hifi_libraries(shared ktx gpu image)
|
||||
|
||||
link_hifi_libraries(shared ktx gpu shaders image)
|
|
@ -11,6 +11,7 @@
|
|||
<@if not MODEL_LIGHT_SLH@>
|
||||
<@def MODEL_LIGHT_SLH@>
|
||||
|
||||
<@include graphics/ShaderConstants.h@>
|
||||
<@include graphics/LightVolume.shared.slh@>
|
||||
<@include graphics/LightIrradiance.shared.slh@>
|
||||
|
||||
|
@ -50,7 +51,7 @@ float getLightAmbientMapNumMips(LightAmbient l) { return l._ambient.y; }
|
|||
|
||||
|
||||
<@if N@>
|
||||
uniform lightBuffer {
|
||||
layout(binding=GRAPHICS_BUFFER_LIGHT) uniform lightBuffer {
|
||||
Light lightArray[<$N$>];
|
||||
};
|
||||
Light getLight(int index) {
|
||||
|
@ -58,7 +59,7 @@ Light getLight(int index) {
|
|||
}
|
||||
|
||||
<@else@>
|
||||
uniform keyLightBuffer {
|
||||
layout(binding=GRAPHICS_BUFFER_KEY_LIGHT) uniform keyLightBuffer {
|
||||
Light light;
|
||||
};
|
||||
Light getKeyLight() {
|
||||
|
@ -78,7 +79,7 @@ Light getKeyLight() {
|
|||
|
||||
<@if N@>
|
||||
|
||||
uniform lightAmbientBuffer {
|
||||
layout(binding=GRAPHICS_BUFFER_AMBIENT_LIGHT) uniform lightAmbientBuffer {
|
||||
LightAmbient lightAmbientArray[<$N$>];
|
||||
};
|
||||
|
||||
|
@ -87,7 +88,7 @@ LightAmbient getLightAmbient(int index) {
|
|||
}
|
||||
|
||||
<@else@>
|
||||
uniform lightAmbientBuffer {
|
||||
layout(binding=GRAPHICS_BUFFER_AMBIENT_LIGHT) uniform lightAmbientBuffer {
|
||||
LightAmbient lightAmbient;
|
||||
};
|
||||
|
||||
|
|
|
@ -11,6 +11,8 @@
|
|||
<@if not MODEL_MATERIAL_SLH@>
|
||||
<@def MODEL_MATERIAL_SLH@>
|
||||
|
||||
<@include graphics/ShaderConstants.h@>
|
||||
|
||||
// The material values (at least the material key) must be precisely bitwise accurate
|
||||
// to what is provided by the uniform buffer, or the material key has the wrong bits
|
||||
|
||||
|
@ -21,7 +23,7 @@ struct Material {
|
|||
vec4 _scatteringSpare2Key;
|
||||
};
|
||||
|
||||
uniform materialBuffer {
|
||||
layout(binding=GRAPHICS_BUFFER_MATERIAL) uniform materialBuffer {
|
||||
Material _mat;
|
||||
};
|
||||
|
||||
|
|
|
@ -11,6 +11,8 @@
|
|||
<@if not MODEL_MATERIAL_TEXTURES_SLH@>
|
||||
<@def MODEL_MATERIAL_TEXTURES_SLH@>
|
||||
|
||||
<@include graphics/ShaderConstants.h@>
|
||||
|
||||
<@func declareMaterialTexMapArrayBuffer()@>
|
||||
|
||||
const int MAX_TEXCOORDS = 2;
|
||||
|
@ -22,7 +24,7 @@ struct TexMapArray {
|
|||
vec4 _lightmapParams;
|
||||
};
|
||||
|
||||
uniform texMapArrayBuffer {
|
||||
layout(binding=GRAPHICS_BUFFER_TEXMAPARRAY) uniform texMapArrayBuffer {
|
||||
TexMapArray _texMapArray;
|
||||
};
|
||||
|
||||
|
@ -123,21 +125,21 @@ float fetchScatteringMap(vec2 uv) {
|
|||
#else
|
||||
|
||||
<@if withAlbedo@>
|
||||
uniform sampler2D albedoMap;
|
||||
layout(binding=GRAPHICS_TEXTURE_MATERIAL_ALBEDO) uniform sampler2D albedoMap;
|
||||
vec4 fetchAlbedoMap(vec2 uv) {
|
||||
return texture(albedoMap, uv, TAA_TEXTURE_LOD_BIAS);
|
||||
}
|
||||
<@endif@>
|
||||
|
||||
<@if withRoughness@>
|
||||
uniform sampler2D roughnessMap;
|
||||
layout(binding=GRAPHICS_TEXTURE_MATERIAL_ROUGHNESS) uniform sampler2D roughnessMap;
|
||||
float fetchRoughnessMap(vec2 uv) {
|
||||
return (texture(roughnessMap, uv, TAA_TEXTURE_LOD_BIAS).r);
|
||||
}
|
||||
<@endif@>
|
||||
|
||||
<@if withNormal@>
|
||||
uniform sampler2D normalMap;
|
||||
layout(binding=GRAPHICS_TEXTURE_MATERIAL_NORMAL) uniform sampler2D normalMap;
|
||||
vec3 fetchNormalMap(vec2 uv) {
|
||||
// unpack normal, swizzle to get into hifi tangent space with Y axis pointing out
|
||||
vec2 t = 2.0 * (texture(normalMap, uv, TAA_TEXTURE_LOD_BIAS).rg - vec2(0.5, 0.5));
|
||||
|
@ -147,28 +149,28 @@ vec3 fetchNormalMap(vec2 uv) {
|
|||
<@endif@>
|
||||
|
||||
<@if withMetallic@>
|
||||
uniform sampler2D metallicMap;
|
||||
layout(binding=GRAPHICS_TEXTURE_MATERIAL_METALLIC) uniform sampler2D metallicMap;
|
||||
float fetchMetallicMap(vec2 uv) {
|
||||
return (texture(metallicMap, uv, TAA_TEXTURE_LOD_BIAS).r);
|
||||
}
|
||||
<@endif@>
|
||||
|
||||
<@if withEmissive@>
|
||||
uniform sampler2D emissiveMap;
|
||||
layout(binding=GRAPHICS_TEXTURE_MATERIAL_EMISSIVE_LIGHTMAP) uniform sampler2D emissiveMap;
|
||||
vec3 fetchEmissiveMap(vec2 uv) {
|
||||
return texture(emissiveMap, uv, TAA_TEXTURE_LOD_BIAS).rgb;
|
||||
}
|
||||
<@endif@>
|
||||
|
||||
<@if withOcclusion@>
|
||||
uniform sampler2D occlusionMap;
|
||||
layout(binding=GRAPHICS_TEXTURE_MATERIAL_OCCLUSION) uniform sampler2D occlusionMap;
|
||||
float fetchOcclusionMap(vec2 uv) {
|
||||
return texture(occlusionMap, uv).r;
|
||||
}
|
||||
<@endif@>
|
||||
|
||||
<@if withScattering@>
|
||||
uniform sampler2D scatteringMap;
|
||||
layout(binding=GRAPHICS_TEXTURE_MATERIAL_SCATTERING) uniform sampler2D scatteringMap;
|
||||
float fetchScatteringMap(vec2 uv) {
|
||||
float scattering = texture(scatteringMap, uv, TAA_TEXTURE_LOD_BIAS).r; // boolean scattering for now
|
||||
return max(((scattering - 0.1) / 0.9), 0.0);
|
||||
|
@ -217,10 +219,10 @@ float fetchScatteringMap(vec2 uv) {
|
|||
|
||||
<$declareMaterialTexMapArrayBuffer()$>
|
||||
|
||||
uniform sampler2D emissiveMap;
|
||||
layout(binding=GRAPHICS_TEXTURE_MATERIAL_EMISSIVE_LIGHTMAP) uniform sampler2D emissiveMap;
|
||||
vec3 fetchLightmapMap(vec2 uv) {
|
||||
vec2 emissiveParams = getTexMapArray()._lightmapParams.xy;
|
||||
return (vec3(emissiveParams.x) + emissiveParams.y * texture(emissiveMap, uv).rgb);
|
||||
vec2 lightmapParams = getTexMapArray()._lightmapParams.xy;
|
||||
return (vec3(lightmapParams.x) + lightmapParams.y * texture(emissiveMap, uv).rgb);
|
||||
}
|
||||
<@endfunc@>
|
||||
|
78
libraries/graphics/src/graphics/ShaderConstants.h
Normal file
78
libraries/graphics/src/graphics/ShaderConstants.h
Normal file
|
@ -0,0 +1,78 @@
|
|||
// <!
|
||||
// Created by Bradley Austin Davis on 2018/05/25
|
||||
// Copyright 2013-2018 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
// !>
|
||||
|
||||
// <@if not GRAPHICS_SHADER_CONSTANTS_H@>
|
||||
// <@def GRAPHICS_SHADER_CONSTANTS_H@>
|
||||
|
||||
// Hack comment to absorb the extra '//' scribe prepends
|
||||
|
||||
#ifndef GRAPHICS_SHADER_CONSTANTS_H
|
||||
#define GRAPHICS_SHADER_CONSTANTS_H
|
||||
|
||||
#define GRAPHICS_BUFFER_SKINNING 0
|
||||
#define GRAPHICS_BUFFER_MATERIAL 1
|
||||
#define GRAPHICS_BUFFER_TEXMAPARRAY 2
|
||||
#define GRAPHICS_BUFFER_KEY_LIGHT 4
|
||||
#define GRAPHICS_BUFFER_LIGHT 5
|
||||
#define GRAPHICS_BUFFER_AMBIENT_LIGHT 6
|
||||
|
||||
#define GRAPHICS_TEXTURE_MATERIAL_ALBEDO 0
|
||||
#define GRAPHICS_TEXTURE_MATERIAL_NORMAL 1
|
||||
#define GRAPHICS_TEXTURE_MATERIAL_METALLIC 2
|
||||
#define GRAPHICS_TEXTURE_MATERIAL_EMISSIVE_LIGHTMAP 3
|
||||
#define GRAPHICS_TEXTURE_MATERIAL_ROUGHNESS 4
|
||||
#define GRAPHICS_TEXTURE_MATERIAL_OCCLUSION 5
|
||||
#define GRAPHICS_TEXTURE_MATERIAL_SCATTERING 6
|
||||
|
||||
// Make sure these match the ones in render-utils/ShaderConstants.h
|
||||
#define GRAPHICS_TEXTURE_SKYBOX 11
|
||||
#define GRAPHICS_BUFFER_SKYBOX_PARAMS 5
|
||||
|
||||
// <!
|
||||
|
||||
namespace graphics { namespace slot {
|
||||
|
||||
namespace buffer {
|
||||
enum Buffer {
|
||||
Skinning = GRAPHICS_BUFFER_SKINNING,
|
||||
Material = GRAPHICS_BUFFER_MATERIAL,
|
||||
TexMapArray = GRAPHICS_BUFFER_TEXMAPARRAY,
|
||||
Light = GRAPHICS_BUFFER_LIGHT,
|
||||
KeyLight = GRAPHICS_BUFFER_KEY_LIGHT,
|
||||
AmbientLight = GRAPHICS_BUFFER_AMBIENT_LIGHT,
|
||||
SkyboxParams = GRAPHICS_BUFFER_SKYBOX_PARAMS
|
||||
};
|
||||
} // namespace buffer
|
||||
|
||||
namespace texture {
|
||||
enum Texture {
|
||||
MaterialAlbedo = GRAPHICS_TEXTURE_MATERIAL_ALBEDO,
|
||||
MaterialNormal = GRAPHICS_TEXTURE_MATERIAL_NORMAL,
|
||||
MaterialMetallic = GRAPHICS_TEXTURE_MATERIAL_METALLIC,
|
||||
MaterialEmissiveLightmap = GRAPHICS_TEXTURE_MATERIAL_EMISSIVE_LIGHTMAP,
|
||||
MaterialRoughness = GRAPHICS_TEXTURE_MATERIAL_ROUGHNESS,
|
||||
MaterialOcclusion = GRAPHICS_TEXTURE_MATERIAL_OCCLUSION,
|
||||
MaterialScattering = GRAPHICS_TEXTURE_MATERIAL_SCATTERING,
|
||||
Skybox = GRAPHICS_TEXTURE_SKYBOX
|
||||
};
|
||||
} // namespace texture
|
||||
|
||||
} } // namespace graphics::slot
|
||||
|
||||
// !>
|
||||
// Hack Comment
|
||||
|
||||
#endif // GRAPHICS_SHADER_CONSTANTS_H
|
||||
|
||||
// <@if 1@>
|
||||
// Trigger Scribe include
|
||||
// <@endif@> <!def that !>
|
||||
|
||||
// <@endif@>
|
||||
|
||||
// Hack Comment
|
|
@ -14,9 +14,8 @@
|
|||
#include <gpu/Batch.h>
|
||||
#include <gpu/Context.h>
|
||||
#include <ViewFrustum.h>
|
||||
|
||||
#include "skybox_vert.h"
|
||||
#include "skybox_frag.h"
|
||||
#include <shaders/Shaders.h>
|
||||
#include "ShaderConstants.h"
|
||||
|
||||
using namespace graphics;
|
||||
|
||||
|
@ -65,17 +64,12 @@ void Skybox::clear() {
|
|||
_empty = true;
|
||||
}
|
||||
|
||||
void Skybox::prepare(gpu::Batch& batch, int textureSlot, int bufferSlot) const {
|
||||
if (bufferSlot > -1) {
|
||||
batch.setUniformBuffer(bufferSlot, _schemaBuffer);
|
||||
}
|
||||
|
||||
if (textureSlot > -1) {
|
||||
gpu::TexturePointer skymap = getCubemap();
|
||||
// FIXME: skymap->isDefined may not be threadsafe
|
||||
if (skymap && skymap->isDefined()) {
|
||||
batch.setResourceTexture(textureSlot, skymap);
|
||||
}
|
||||
void Skybox::prepare(gpu::Batch& batch) const {
|
||||
batch.setUniformBuffer(graphics::slot::buffer::SkyboxParams, _schemaBuffer);
|
||||
gpu::TexturePointer skymap = getCubemap();
|
||||
// FIXME: skymap->isDefined may not be threadsafe
|
||||
if (skymap && skymap->isDefined()) {
|
||||
batch.setResourceTexture(graphics::slot::texture::Skybox, skymap);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -91,19 +85,7 @@ void Skybox::render(gpu::Batch& batch, const ViewFrustum& viewFrustum, const Sky
|
|||
static std::once_flag once;
|
||||
std::call_once(once, [&] {
|
||||
{
|
||||
auto skyVS = skybox_vert::getShader();
|
||||
auto skyFS = skybox_frag::getShader();
|
||||
auto skyShader = gpu::Shader::createProgram(skyVS, skyFS);
|
||||
|
||||
batch.runLambda([skyShader] {
|
||||
gpu::Shader::BindingSet bindings;
|
||||
bindings.insert(gpu::Shader::Binding(std::string("cubeMap"), SKYBOX_SKYMAP_SLOT));
|
||||
bindings.insert(gpu::Shader::Binding(std::string("skyboxBuffer"), SKYBOX_CONSTANTS_SLOT));
|
||||
if (!gpu::Shader::makeProgram(*skyShader, bindings)) {
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
auto skyShader = gpu::Shader::createProgram(shader::graphics::program::skybox);
|
||||
auto skyState = std::make_shared<gpu::State>();
|
||||
// Must match PrepareStencil::STENCIL_BACKGROUND
|
||||
const int8_t STENCIL_BACKGROUND = 0;
|
||||
|
@ -133,5 +115,5 @@ void Skybox::render(gpu::Batch& batch, const ViewFrustum& viewFrustum, const Sky
|
|||
skybox.prepare(batch);
|
||||
batch.draw(gpu::TRIANGLE_STRIP, 4);
|
||||
|
||||
batch.setResourceTexture(SKYBOX_SKYMAP_SLOT, nullptr);
|
||||
batch.setResourceTexture(graphics::slot::texture::Skybox, nullptr);
|
||||
}
|
||||
|
|
|
@ -43,7 +43,7 @@ public:
|
|||
virtual bool empty() { return _empty; }
|
||||
virtual void clear();
|
||||
|
||||
void prepare(gpu::Batch& batch, int textureSlot = SKYBOX_SKYMAP_SLOT, int bufferSlot = SKYBOX_CONSTANTS_SLOT) const;
|
||||
void prepare(gpu::Batch& batch) const;
|
||||
virtual void render(gpu::Batch& batch, const ViewFrustum& frustum) const;
|
||||
|
||||
static void render(gpu::Batch& batch, const ViewFrustum& frustum, const Skybox& skybox);
|
||||
|
@ -51,9 +51,6 @@ public:
|
|||
const UniformBufferView& getSchemaBuffer() const { return _schemaBuffer; }
|
||||
|
||||
protected:
|
||||
static const int SKYBOX_SKYMAP_SLOT { 0 };
|
||||
static const int SKYBOX_CONSTANTS_SLOT { 0 };
|
||||
|
||||
class Schema {
|
||||
public:
|
||||
glm::vec3 color { 0.0f, 0.0f, 0.0f };
|
||||
|
|
|
@ -10,42 +10,22 @@
|
|||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
<@include graphics/ShaderConstants.h@>
|
||||
|
||||
uniform samplerCube cubeMap;
|
||||
layout(binding=GRAPHICS_TEXTURE_SKYBOX) uniform samplerCube cubeMap;
|
||||
|
||||
struct Skybox {
|
||||
vec4 color;
|
||||
};
|
||||
|
||||
uniform skyboxBuffer {
|
||||
layout(binding=GRAPHICS_BUFFER_SKYBOX_PARAMS) uniform skyboxBuffer {
|
||||
Skybox skybox;
|
||||
};
|
||||
|
||||
in vec3 _normal;
|
||||
out vec4 _fragColor;
|
||||
layout(location=0) in vec3 _normal;
|
||||
layout(location=0) out vec4 _fragColor;
|
||||
|
||||
//PROCEDURAL_COMMON_BLOCK
|
||||
|
||||
#line 1001
|
||||
//PROCEDURAL_BLOCK
|
||||
|
||||
#line 2033
|
||||
void main(void) {
|
||||
|
||||
#ifdef PROCEDURAL
|
||||
|
||||
vec3 color = getSkyboxColor();
|
||||
// Protect from NaNs and negative values
|
||||
color = mix(color, vec3(0), isnan(color));
|
||||
color = max(color, vec3(0));
|
||||
// Procedural Shaders are expected to be Gamma corrected so let's bring back the RGB in linear space for the rest of the pipeline
|
||||
color = pow(color, vec3(2.2));
|
||||
_fragColor = vec4(color, 0.0);
|
||||
|
||||
// FIXME: scribe does not yet scrub out else statements
|
||||
return;
|
||||
|
||||
#else
|
||||
vec3 coord = normalize(_normal);
|
||||
vec3 color = skybox.color.rgb;
|
||||
|
||||
|
@ -57,7 +37,4 @@ void main(void) {
|
|||
}
|
||||
}
|
||||
_fragColor = vec4(color, 0.0);
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
|
||||
<$declareStandardTransform()$>
|
||||
|
||||
out vec3 _normal;
|
||||
layout(location=0) out vec3 _normal;
|
||||
|
||||
void main(void) {
|
||||
const float depth = 0.0;
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
set(TARGET_NAME procedural)
|
||||
AUTOSCRIBE_SHADER_LIB(gpu graphics)
|
||||
setup_hifi_library()
|
||||
link_hifi_libraries(shared gpu networking graphics model-networking ktx image)
|
||||
link_hifi_libraries(shared gpu shaders networking graphics model-networking ktx image)
|
||||
|
||||
|
|
|
@ -11,6 +11,6 @@
|
|||
|
||||
#include <QLoggingCategory>
|
||||
|
||||
Q_DECLARE_LOGGING_CATEGORY(procedural)
|
||||
Q_DECLARE_LOGGING_CATEGORY(proceduralLog)
|
||||
|
||||
#endif // hifi_octree_Logging_h
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue