merge latest master changes

This commit is contained in:
Rodolfo Bogado
2017-05-13 12:35:28 -03:00
parent ee67f8cdea
commit d462ca3872
148 changed files with 5379 additions and 3899 deletions

View File

@@ -1,6 +1,6 @@
// ****************************************************************************
// * This file is part of the HqMAME project. It is distributed under *
// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
// * GNU General Public License: http://www.gnu.org/licenses/gpl-3.0 *
// * Copyright (C) Zenju (zenju AT gmx DOT de) - All Rights Reserved *
// * *
// * Additionally and as a special exception, the author gives permission *
@@ -22,18 +22,11 @@ namespace xbrz
{
struct ScalerCfg
{
ScalerCfg() :
luminanceWeight_(1),
equalColorTolerance_(30),
dominantDirectionThreshold(3.6),
steepDirectionThreshold(2.2),
newTestAttribute_(0) {}
double luminanceWeight_;
double equalColorTolerance_;
double dominantDirectionThreshold;
double steepDirectionThreshold;
double newTestAttribute_; //unused; test new parameters
double luminanceWeight = 1;
double equalColorTolerance = 30;
double dominantDirectionThreshold = 3.6;
double steepDirectionThreshold = 2.2;
double newTestAttribute = 0; //unused; test new parameters
};
}

File diff suppressed because it is too large Load Diff

54
Externals/xbrz/xbrz.h vendored
View File

@@ -1,6 +1,6 @@
// ****************************************************************************
// * This file is part of the HqMAME project. It is distributed under *
// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
// * GNU General Public License: http://www.gnu.org/licenses/gpl-3.0 *
// * Copyright (C) Zenju (zenju AT gmx DOT de) - All Rights Reserved *
// * *
// * Additionally and as a special exception, the author gives permission *
@@ -16,15 +16,8 @@
#ifndef XBRZ_HEADER_3847894708239054
#define XBRZ_HEADER_3847894708239054
#undef min
#undef max
#include <cstddef> //size_t
#if defined(IOS)
#include <stdint.h>
#else
#include <cstdint> //uint32_t
#endif
#include <limits>
#include "config.h"
@@ -42,46 +35,43 @@ http://board.byuu.org/viewtopic.php?f=10&t=2248
- support multithreading
- support 64-bit architectures
- support processing image slices
- support scaling up to 6xBRZ
*/
enum class ColorFormat //from high bits -> low bits, 8 bit per channel
{
ARGB, //including alpha channel, BGRA byte order on little-endian machines
RGB, //8 bit for each red, green, blue, upper 8 bits unused
RGB, //8 bit for each red, green, blue, upper 8 bits unused
ARGB, //including alpha channel, BGRA byte order on little-endian machines
};
/*
-> map source (srcWidth * srcHeight) to target (scale * width x scale * height) image, optionally processing a half-open slice of rows [yFirst, yLast) only
-> support for source/target pitch in bytes!
-> if your emulator changes only a few image slices during each cycle (e.g. DOSBox) then there's no need to run xBRZ on the complete image:
Just make sure you enlarge the source image slice by 2 rows on top and 2 on bottom (this is the additional range the xBRZ algorithm is using during analysis)
Caveat: If there are multiple changed slices, make sure they do not overlap after adding these additional rows in order to avoid a memory race condition
in the target image data if you are using multiple threads for processing each enlarged slice!
Just make sure you enlarge the source image slice by 2 rows on top and 2 on bottom (this is the additional range the xBRZ algorithm is using during analysis)
Caveat: If there are multiple changed slices, make sure they do not overlap after adding these additional rows in order to avoid a memory race condition
in the target image data if you are using multiple threads for processing each enlarged slice!
THREAD-SAFETY: - parts of the same image may be scaled by multiple threads as long as the [yFirst, yLast) ranges do not overlap!
- there is a minor inefficiency for the first row of a slice, so avoid processing single rows only; suggestion: process 6 rows at least
- there is a minor inefficiency for the first row of a slice, so avoid processing single rows only; suggestion: process 8-16 rows at least
*/
void scale(size_t factor, //valid range: 2 - 5
const uint32_t* src, uint32_t* trg, int srcWidth, int srcHeight,
ColorFormat colFmt,
const ScalerCfg& cfg = ScalerCfg(),
int yFirst = 0, int yLast = std::numeric_limits<int>::max()); //slice of source image
void init();
void shutdown();
void scale(size_t factor, //valid range: 2 - 6
const uint32_t* src, uint32_t* trg, int srcWidth, int srcHeight,
ColorFormat colFmt,
const ScalerCfg& cfg = ScalerCfg(),
int yFirst = 0, int yLast = std::numeric_limits<int>::max()); //slice of source image
void nearestNeighborScale(const uint32_t* src, int srcWidth, int srcHeight,
uint32_t* trg, int trgWidth, int trgHeight);
uint32_t* trg, int trgWidth, int trgHeight);
enum SliceType
{
NN_SCALE_SLICE_SOURCE,
NN_SCALE_SLICE_TARGET,
NN_SCALE_SLICE_SOURCE,
NN_SCALE_SLICE_TARGET,
};
void nearestNeighborScale(const uint32_t* src, int srcWidth, int srcHeight, int srcPitch, //pitch in bytes!
uint32_t* trg, int trgWidth, int trgHeight, int trgPitch,
SliceType st, int yFirst, int yLast);
uint32_t* trg, int trgWidth, int trgHeight, int trgPitch,
SliceType st, int yFirst, int yLast);
//parameter tuning
bool equalColorTest(uint32_t col1, uint32_t col2, ColorFormat colFmt, double luminanceWeight, double equalColorTolerance);
@@ -93,11 +83,11 @@ bool equalColorTest(uint32_t col1, uint32_t col2, ColorFormat colFmt, double lum
//########################### implementation ###########################
inline
void nearestNeighborScale(const uint32_t* src, int srcWidth, int srcHeight,
uint32_t* trg, int trgWidth, int trgHeight)
uint32_t* trg, int trgWidth, int trgHeight)
{
nearestNeighborScale(src, srcWidth, srcHeight, srcWidth * sizeof(uint32_t),
trg, trgWidth, trgHeight, trgWidth * sizeof(uint32_t),
NN_SCALE_SLICE_TARGET, 0, trgHeight);
nearestNeighborScale(src, srcWidth, srcHeight, srcWidth * sizeof(uint32_t),
trg, trgWidth, trgHeight, trgWidth * sizeof(uint32_t),
NN_SCALE_SLICE_TARGET, 0, trgHeight);
}
}

View File

@@ -71,6 +71,7 @@
<ClInclude Include="GL\GLExtensions\ARB_blend_func_extended.h" />
<ClInclude Include="GL\GLExtensions\ARB_buffer_storage.h" />
<ClInclude Include="GL\GLExtensions\ARB_clip_control.h" />
<ClInclude Include="GL\GLExtensions\ARB_compute_shader.h" />
<ClInclude Include="GL\GLExtensions\ARB_copy_image.h" />
<ClInclude Include="GL\GLExtensions\ARB_debug_output.h" />
<ClInclude Include="GL\GLExtensions\ARB_draw_elements_base_vertex.h" />
@@ -85,10 +86,12 @@
<ClInclude Include="GL\GLExtensions\ARB_shader_storage_buffer_object.h" />
<ClInclude Include="GL\GLExtensions\ARB_sync.h" />
<ClInclude Include="GL\GLExtensions\ARB_texture_multisample.h" />
<ClInclude Include="GL\GLExtensions\ARB_texture_storage.h" />
<ClInclude Include="GL\GLExtensions\ARB_texture_storage_multisample.h" />
<ClInclude Include="GL\GLExtensions\ARB_uniform_buffer_object.h" />
<ClInclude Include="GL\GLExtensions\ARB_vertex_array_object.h" />
<ClInclude Include="GL\GLExtensions\ARB_viewport_array.h" />
<ClInclude Include="GL\GLExtensions\EXT_texture_compression_s3tc.h" />
<ClInclude Include="GL\GLExtensions\EXT_texture_filter_anisotropic.h" />
<ClInclude Include="GL\GLExtensions\GLExtensions.h" />
<ClInclude Include="GL\GLExtensions\gl_1_1.h" />
@@ -108,6 +111,7 @@
<ClInclude Include="GL\GLExtensions\gl_common.h" />
<ClInclude Include="GL\GLExtensions\HP_occlusion_test.h" />
<ClInclude Include="GL\GLExtensions\KHR_debug.h" />
<ClInclude Include="GL\GLExtensions\NV_depth_buffer_float.h" />
<ClInclude Include="GL\GLExtensions\NV_occlusion_query_samples.h" />
<ClInclude Include="GL\GLExtensions\NV_primitive_restart.h" />
<ClInclude Include="GL\GLInterfaceBase.h" />

View File

@@ -232,6 +232,18 @@
<ClInclude Include="Align.h" />
<ClInclude Include="BitHelpers.h" />
<ClInclude Include="AllocationMap.h" />
<ClInclude Include="GL\GLExtensions\ARB_compute_shader.h">
<Filter>GL\GLExtensions</Filter>
</ClInclude>
<ClInclude Include="GL\GLExtensions\ARB_texture_storage.h">
<Filter>GL\GLExtensions</Filter>
</ClInclude>
<ClInclude Include="GL\GLExtensions\EXT_texture_compression_s3tc.h">
<Filter>GL\GLExtensions</Filter>
</ClInclude>
<ClInclude Include="GL\GLExtensions\NV_depth_buffer_float.h">
<Filter>GL\GLExtensions</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="BreakPoints.cpp" />

View File

@@ -0,0 +1,53 @@
/*
** Copyright (c) 2013-2015 The Khronos Group Inc.
**
** Permission is hereby granted, free of charge, to any person obtaining a
** copy of this software and/or associated documentation files (the
** "Materials"), to deal in the Materials without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Materials, and to
** permit persons to whom the Materials are furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be included
** in all copies or substantial portions of the Materials.
**
** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
*/
#include "Common/GL/GLExtensions/gl_common.h"
#define GL_COMPUTE_SHADER 0x91B9
#define GL_MAX_COMPUTE_UNIFORM_BLOCKS 0x91BB
#define GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS 0x91BC
#define GL_MAX_COMPUTE_IMAGE_UNIFORMS 0x91BD
#define GL_MAX_COMPUTE_SHARED_MEMORY_SIZE 0x8262
#define GL_MAX_COMPUTE_UNIFORM_COMPONENTS 0x8263
#define GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS 0x8264
#define GL_MAX_COMPUTE_ATOMIC_COUNTERS 0x8265
#define GL_MAX_COMBINED_COMPUTE_UNIFORM_COMPONENTS 0x8266
#define GL_MAX_COMPUTE_WORK_GROUP_INVOCATIONS 0x90EB
#define GL_MAX_COMPUTE_WORK_GROUP_COUNT 0x91BE
#define GL_MAX_COMPUTE_WORK_GROUP_SIZE 0x91BF
#define GL_COMPUTE_WORK_GROUP_SIZE 0x8267
#define GL_UNIFORM_BLOCK_REFERENCED_BY_COMPUTE_SHADER 0x90EC
#define GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_COMPUTE_SHADER 0x90ED
#define GL_DISPATCH_INDIRECT_BUFFER 0x90EE
#define GL_DISPATCH_INDIRECT_BUFFER_BINDING 0x90EF
#define GL_COMPUTE_SHADER_BIT 0x00000020
typedef void(APIENTRYP PFNDOLDISPATCHCOMPUTEPROC)(GLuint num_groups_x, GLuint num_groups_y,
GLuint num_groups_z);
typedef void(APIENTRYP PFNDOLDISPATCHCOMPUTEINDIRECTPROC)(GLintptr indirect);
extern PFNDOLDISPATCHCOMPUTEPROC dolDispatchCompute;
extern PFNDOLDISPATCHCOMPUTEINDIRECTPROC dolDispatchComputeIndirect;
#define glDispatchCompute dolDispatchCompute
#define glDispatchComputeIndirect dolDispatchComputeIndirect

View File

@@ -0,0 +1,100 @@
/*
** Copyright (c) 2013-2015 The Khronos Group Inc.
**
** Permission is hereby granted, free of charge, to any person obtaining a
** copy of this software and/or associated documentation files (the
** "Materials"), to deal in the Materials without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Materials, and to
** permit persons to whom the Materials are furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be included
** in all copies or substantial portions of the Materials.
**
** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
*/
#include "Common/GL/GLExtensions/gl_common.h"
#define GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT 0x00000001
#define GL_ELEMENT_ARRAY_BARRIER_BIT 0x00000002
#define GL_UNIFORM_BARRIER_BIT 0x00000004
#define GL_TEXTURE_FETCH_BARRIER_BIT 0x00000008
#define GL_SHADER_IMAGE_ACCESS_BARRIER_BIT 0x00000020
#define GL_COMMAND_BARRIER_BIT 0x00000040
#define GL_PIXEL_BUFFER_BARRIER_BIT 0x00000080
#define GL_TEXTURE_UPDATE_BARRIER_BIT 0x00000100
#define GL_BUFFER_UPDATE_BARRIER_BIT 0x00000200
#define GL_FRAMEBUFFER_BARRIER_BIT 0x00000400
#define GL_TRANSFORM_FEEDBACK_BARRIER_BIT 0x00000800
#define GL_ATOMIC_COUNTER_BARRIER_BIT 0x00001000
#define GL_ALL_BARRIER_BITS 0xFFFFFFFF
#define GL_MAX_IMAGE_UNITS 0x8F38
#define GL_MAX_COMBINED_IMAGE_UNITS_AND_FRAGMENT_OUTPUTS 0x8F39
#define GL_IMAGE_BINDING_NAME 0x8F3A
#define GL_IMAGE_BINDING_LEVEL 0x8F3B
#define GL_IMAGE_BINDING_LAYERED 0x8F3C
#define GL_IMAGE_BINDING_LAYER 0x8F3D
#define GL_IMAGE_BINDING_ACCESS 0x8F3E
#define GL_IMAGE_1D 0x904C
#define GL_IMAGE_2D 0x904D
#define GL_IMAGE_3D 0x904E
#define GL_IMAGE_2D_RECT 0x904F
#define GL_IMAGE_CUBE 0x9050
#define GL_IMAGE_BUFFER 0x9051
#define GL_IMAGE_1D_ARRAY 0x9052
#define GL_IMAGE_2D_ARRAY 0x9053
#define GL_IMAGE_CUBE_MAP_ARRAY 0x9054
#define GL_IMAGE_2D_MULTISAMPLE 0x9055
#define GL_IMAGE_2D_MULTISAMPLE_ARRAY 0x9056
#define GL_INT_IMAGE_1D 0x9057
#define GL_INT_IMAGE_2D 0x9058
#define GL_INT_IMAGE_3D 0x9059
#define GL_INT_IMAGE_2D_RECT 0x905A
#define GL_INT_IMAGE_CUBE 0x905B
#define GL_INT_IMAGE_BUFFER 0x905C
#define GL_INT_IMAGE_1D_ARRAY 0x905D
#define GL_INT_IMAGE_2D_ARRAY 0x905E
#define GL_INT_IMAGE_CUBE_MAP_ARRAY 0x905F
#define GL_INT_IMAGE_2D_MULTISAMPLE 0x9060
#define GL_INT_IMAGE_2D_MULTISAMPLE_ARRAY 0x9061
#define GL_UNSIGNED_INT_IMAGE_1D 0x9062
#define GL_UNSIGNED_INT_IMAGE_2D 0x9063
#define GL_UNSIGNED_INT_IMAGE_3D 0x9064
#define GL_UNSIGNED_INT_IMAGE_2D_RECT 0x9065
#define GL_UNSIGNED_INT_IMAGE_CUBE 0x9066
#define GL_UNSIGNED_INT_IMAGE_BUFFER 0x9067
#define GL_UNSIGNED_INT_IMAGE_1D_ARRAY 0x9068
#define GL_UNSIGNED_INT_IMAGE_2D_ARRAY 0x9069
#define GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY 0x906A
#define GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE 0x906B
#define GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY 0x906C
#define GL_MAX_IMAGE_SAMPLES 0x906D
#define GL_IMAGE_BINDING_FORMAT 0x906E
#define GL_IMAGE_FORMAT_COMPATIBILITY_TYPE 0x90C7
#define GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE 0x90C8
#define GL_IMAGE_FORMAT_COMPATIBILITY_BY_CLASS 0x90C9
#define GL_MAX_VERTEX_IMAGE_UNIFORMS 0x90CA
#define GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS 0x90CB
#define GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS 0x90CC
#define GL_MAX_GEOMETRY_IMAGE_UNIFORMS 0x90CD
#define GL_MAX_FRAGMENT_IMAGE_UNIFORMS 0x90CE
#define GL_MAX_COMBINED_IMAGE_UNIFORMS 0x90CF
typedef void(APIENTRYP PFNDOLBINDIMAGETEXTUREPROC)(GLuint unit, GLuint texture, GLint level,
GLboolean layered, GLint layer, GLenum access,
GLenum format);
typedef void(APIENTRYP PFNDOLMEMORYBARRIERPROC)(GLbitfield barriers);
extern PFNDOLBINDIMAGETEXTUREPROC dolBindImageTexture;
extern PFNDOLMEMORYBARRIERPROC dolMemoryBarrier;
#define glBindImageTexture dolBindImageTexture
#define glMemoryBarrier dolMemoryBarrier

View File

@@ -0,0 +1,41 @@
/*
** Copyright (c) 2013-2015 The Khronos Group Inc.
**
** Permission is hereby granted, free of charge, to any person obtaining a
** copy of this software and/or associated documentation files (the
** "Materials"), to deal in the Materials without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Materials, and to
** permit persons to whom the Materials are furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be included
** in all copies or substantial portions of the Materials.
**
** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
*/
#include "Common/GL/GLExtensions/gl_common.h"
#define GL_TEXTURE_IMMUTABLE_FORMAT 0x912F
typedef void(APIENTRYP PFNDOLTEXSTORAGE1DPROC)(GLenum target, GLsizei levels, GLenum internalformat,
GLsizei width);
typedef void(APIENTRYP PFNDOLTEXSTORAGE2DPROC)(GLenum target, GLsizei levels, GLenum internalformat,
GLsizei width, GLsizei height);
typedef void(APIENTRYP PFNDOLTEXSTORAGE3DPROC)(GLenum target, GLsizei levels, GLenum internalformat,
GLsizei width, GLsizei height, GLsizei depth);
extern PFNDOLTEXSTORAGE1DPROC dolTexStorage1D;
extern PFNDOLTEXSTORAGE2DPROC dolTexStorage2D;
extern PFNDOLTEXSTORAGE3DPROC dolTexStorage3D;
#define glTexStorage1D dolTexStorage1D
#define glTexStorage2D dolTexStorage2D
#define glTexStorage3D dolTexStorage3D

View File

@@ -0,0 +1,29 @@
/*
** Copyright (c) 2013-2015 The Khronos Group Inc.
**
** Permission is hereby granted, free of charge, to any person obtaining a
** copy of this software and/or associated documentation files (the
** "Materials"), to deal in the Materials without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Materials, and to
** permit persons to whom the Materials are furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be included
** in all copies or substantial portions of the Materials.
**
** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
*/
#include "Common/GL/GLExtensions/gl_common.h"
#define GL_COMPRESSED_RGB_S3TC_DXT1_EXT 0x83F0
#define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1
#define GL_COMPRESSED_RGBA_S3TC_DXT3_EXT 0x83F2
#define GL_COMPRESSED_RGBA_S3TC_DXT5_EXT 0x83F3

View File

@@ -653,19 +653,12 @@ PFNDOLDRAWELEMENTSINSTANCEDBASEVERTEXBASEINSTANCEPROC
dolDrawElementsInstancedBaseVertexBaseInstance;
PFNDOLGETINTERNALFORMATIVPROC dolGetInternalformativ;
PFNDOLGETACTIVEATOMICCOUNTERBUFFERIVPROC dolGetActiveAtomicCounterBufferiv;
PFNDOLBINDIMAGETEXTUREPROC dolBindImageTexture;
PFNDOLMEMORYBARRIERPROC dolMemoryBarrier;
PFNDOLTEXSTORAGE1DPROC dolTexStorage1D;
PFNDOLTEXSTORAGE2DPROC dolTexStorage2D;
PFNDOLTEXSTORAGE3DPROC dolTexStorage3D;
PFNDOLDRAWTRANSFORMFEEDBACKINSTANCEDPROC dolDrawTransformFeedbackInstanced;
PFNDOLDRAWTRANSFORMFEEDBACKSTREAMINSTANCEDPROC dolDrawTransformFeedbackStreamInstanced;
// gl_4_3
PFNDOLCLEARBUFFERDATAPROC dolClearBufferData;
PFNDOLCLEARBUFFERSUBDATAPROC dolClearBufferSubData;
PFNDOLDISPATCHCOMPUTEPROC dolDispatchCompute;
PFNDOLDISPATCHCOMPUTEINDIRECTPROC dolDispatchComputeIndirect;
PFNDOLFRAMEBUFFERPARAMETERIPROC dolFramebufferParameteri;
PFNDOLGETFRAMEBUFFERPARAMETERIVPROC dolGetFramebufferParameteriv;
PFNDOLGETINTERNALFORMATI64VPROC dolGetInternalformati64v;
@@ -905,6 +898,11 @@ PFNDOLTEXIMAGE3DMULTISAMPLEPROC dolTexImage3DMultisample;
PFNDOLGETMULTISAMPLEFVPROC dolGetMultisamplefv;
PFNDOLSAMPLEMASKIPROC dolSampleMaski;
// ARB_texture_storage
PFNDOLTEXSTORAGE1DPROC dolTexStorage1D;
PFNDOLTEXSTORAGE2DPROC dolTexStorage2D;
PFNDOLTEXSTORAGE3DPROC dolTexStorage3D;
// ARB_texture_storage_multisample
PFNDOLTEXSTORAGE2DMULTISAMPLEPROC dolTexStorage2DMultisample;
PFNDOLTEXSTORAGE3DMULTISAMPLEPROC dolTexStorage3DMultisample;
@@ -984,6 +982,19 @@ PFNDOLCOPYIMAGESUBDATAPROC dolCopyImageSubData;
// ARB_shader_storage_buffer_object
PFNDOLSHADERSTORAGEBLOCKBINDINGPROC dolShaderStorageBlockBinding;
// NV_depth_buffer_float
PFNDOLDEPTHRANGEDNVPROC dolDepthRangedNV;
PFNDOLCLEARDEPTHDNVPROC dolClearDepthdNV;
PFNDOLDEPTHBOUNDSDNVPROC dolDepthBoundsdNV;
// ARB_shader_image_load_store
PFNDOLBINDIMAGETEXTUREPROC dolBindImageTexture;
PFNDOLMEMORYBARRIERPROC dolMemoryBarrier;
// ARB_compute_shader
PFNDOLDISPATCHCOMPUTEPROC dolDispatchCompute;
PFNDOLDISPATCHCOMPUTEINDIRECTPROC dolDispatchComputeIndirect;
// Creates a GLFunc object that requires a feature
#define GLFUNC_REQUIRES(x, y) \
{ \
@@ -1625,123 +1636,128 @@ const GLFunc gl_function_array[] = {
// APPLE_vertex_array_object
GLFUNC_SUFFIX(glBindVertexArray, APPLE,
"GL_APPLE_vertex_array_object !GL_ARB_vertex_array_object"),
"GL_APPLE_vertex_array_object !GL_ARB_vertex_array_object"),
GLFUNC_SUFFIX(glDeleteVertexArrays, APPLE,
"GL_APPLE_vertex_array_object !GL_ARB_vertex_array_object"),
"GL_APPLE_vertex_array_object !GL_ARB_vertex_array_object"),
GLFUNC_SUFFIX(glGenVertexArrays, APPLE,
"GL_APPLE_vertex_array_object !GL_ARB_vertex_array_object"),
"GL_APPLE_vertex_array_object !GL_ARB_vertex_array_object"),
GLFUNC_SUFFIX(glIsVertexArray, APPLE,
"GL_APPLE_vertex_array_object !GL_ARB_vertex_array_object"),
"GL_APPLE_vertex_array_object !GL_ARB_vertex_array_object"),
// ARB_framebuffer_object
GLFUNC_REQUIRES(glFramebufferTexture1D, "GL_ARB_framebuffer_object"),
GLFUNC_REQUIRES(glFramebufferTexture3D, "GL_ARB_framebuffer_object"),
GLFUNC_REQUIRES(glBindFramebuffer, "GL_ARB_framebuffer_object |VERSION_GLES_2"),
GLFUNC_REQUIRES(glBindRenderbuffer, "GL_ARB_framebuffer_object |VERSION_GLES_2"),
GLFUNC_REQUIRES(glBlitFramebuffer, "GL_ARB_framebuffer_object |VERSION_GLES_3"),
GLFUNC_REQUIRES(glCheckFramebufferStatus, "GL_ARB_framebuffer_object |VERSION_GLES_2"),
GLFUNC_REQUIRES(glDeleteFramebuffers, "GL_ARB_framebuffer_object |VERSION_GLES_2"),
GLFUNC_REQUIRES(glDeleteRenderbuffers, "GL_ARB_framebuffer_object |VERSION_GLES_2"),
GLFUNC_REQUIRES(glFramebufferRenderbuffer, "GL_ARB_framebuffer_object |VERSION_GLES_2"),
GLFUNC_REQUIRES(glFramebufferTexture2D, "GL_ARB_framebuffer_object |VERSION_GLES_2"),
GLFUNC_REQUIRES(glFramebufferTextureLayer, "GL_ARB_framebuffer_object |VERSION_GLES_3"),
GLFUNC_REQUIRES(glGenFramebuffers, "GL_ARB_framebuffer_object |VERSION_GLES_2"),
GLFUNC_REQUIRES(glGenRenderbuffers, "GL_ARB_framebuffer_object |VERSION_GLES_2"),
GLFUNC_REQUIRES(glGenerateMipmap, "GL_ARB_framebuffer_object |VERSION_GLES_2"),
GLFUNC_REQUIRES(glGetFramebufferAttachmentParameteriv,
"GL_ARB_framebuffer_object |VERSION_GLES_2"),
GLFUNC_REQUIRES(glGetRenderbufferParameteriv, "GL_ARB_framebuffer_object |VERSION_GLES_2"),
GLFUNC_REQUIRES(glIsFramebuffer, "GL_ARB_framebuffer_object |VERSION_GLES_2"),
GLFUNC_REQUIRES(glIsRenderbuffer, "GL_ARB_framebuffer_object |VERSION_GLES_2"),
GLFUNC_REQUIRES(glRenderbufferStorage, "GL_ARB_framebuffer_object |VERSION_GLES_2"),
GLFUNC_REQUIRES(glRenderbufferStorageMultisample, "GL_ARB_framebuffer_object |VERSION_GLES_3"),
// ARB_framebuffer_object
GLFUNC_REQUIRES(glFramebufferTexture1D, "GL_ARB_framebuffer_object"),
GLFUNC_REQUIRES(glFramebufferTexture3D, "GL_ARB_framebuffer_object"),
GLFUNC_REQUIRES(glBindFramebuffer, "GL_ARB_framebuffer_object |VERSION_GLES_2"),
GLFUNC_REQUIRES(glBindRenderbuffer, "GL_ARB_framebuffer_object |VERSION_GLES_2"),
GLFUNC_REQUIRES(glBlitFramebuffer, "GL_ARB_framebuffer_object |VERSION_GLES_3"),
GLFUNC_REQUIRES(glCheckFramebufferStatus, "GL_ARB_framebuffer_object |VERSION_GLES_2"),
GLFUNC_REQUIRES(glDeleteFramebuffers, "GL_ARB_framebuffer_object |VERSION_GLES_2"),
GLFUNC_REQUIRES(glDeleteRenderbuffers, "GL_ARB_framebuffer_object |VERSION_GLES_2"),
GLFUNC_REQUIRES(glFramebufferRenderbuffer, "GL_ARB_framebuffer_object |VERSION_GLES_2"),
GLFUNC_REQUIRES(glFramebufferTexture2D, "GL_ARB_framebuffer_object |VERSION_GLES_2"),
GLFUNC_REQUIRES(glFramebufferTextureLayer, "GL_ARB_framebuffer_object |VERSION_GLES_3"),
GLFUNC_REQUIRES(glGenFramebuffers, "GL_ARB_framebuffer_object |VERSION_GLES_2"),
GLFUNC_REQUIRES(glGenRenderbuffers, "GL_ARB_framebuffer_object |VERSION_GLES_2"),
GLFUNC_REQUIRES(glGenerateMipmap, "GL_ARB_framebuffer_object |VERSION_GLES_2"),
GLFUNC_REQUIRES(glGetFramebufferAttachmentParameteriv,
"GL_ARB_framebuffer_object |VERSION_GLES_2"),
GLFUNC_REQUIRES(glGetRenderbufferParameteriv, "GL_ARB_framebuffer_object |VERSION_GLES_2"),
GLFUNC_REQUIRES(glIsFramebuffer, "GL_ARB_framebuffer_object |VERSION_GLES_2"),
GLFUNC_REQUIRES(glIsRenderbuffer, "GL_ARB_framebuffer_object |VERSION_GLES_2"),
GLFUNC_REQUIRES(glRenderbufferStorage, "GL_ARB_framebuffer_object |VERSION_GLES_2"),
GLFUNC_REQUIRES(glRenderbufferStorageMultisample, "GL_ARB_framebuffer_object |VERSION_GLES_3"),
// ARB_get_program_binary
GLFUNC_REQUIRES(glGetProgramBinary, "GL_ARB_get_program_binary |VERSION_GLES_3"),
GLFUNC_REQUIRES(glProgramBinary, "GL_ARB_get_program_binary |VERSION_GLES_3"),
GLFUNC_REQUIRES(glProgramParameteri, "GL_ARB_get_program_binary |VERSION_GLES_3"),
// ARB_get_program_binary
GLFUNC_REQUIRES(glGetProgramBinary, "GL_ARB_get_program_binary |VERSION_GLES_3"),
GLFUNC_REQUIRES(glProgramBinary, "GL_ARB_get_program_binary |VERSION_GLES_3"),
GLFUNC_REQUIRES(glProgramParameteri, "GL_ARB_get_program_binary |VERSION_GLES_3"),
// ARB_sync
GLFUNC_REQUIRES(glClientWaitSync, "GL_ARB_sync |VERSION_GLES_3"),
GLFUNC_REQUIRES(glDeleteSync, "GL_ARB_sync |VERSION_GLES_3"),
GLFUNC_REQUIRES(glFenceSync, "GL_ARB_sync |VERSION_GLES_3"),
GLFUNC_REQUIRES(glGetInteger64v, "GL_ARB_sync |VERSION_GLES_3"),
GLFUNC_REQUIRES(glGetSynciv, "GL_ARB_sync |VERSION_GLES_3"),
GLFUNC_REQUIRES(glIsSync, "GL_ARB_sync |VERSION_GLES_3"),
GLFUNC_REQUIRES(glWaitSync, "GL_ARB_sync |VERSION_GLES_3"),
// ARB_sync
GLFUNC_REQUIRES(glClientWaitSync, "GL_ARB_sync |VERSION_GLES_3"),
GLFUNC_REQUIRES(glDeleteSync, "GL_ARB_sync |VERSION_GLES_3"),
GLFUNC_REQUIRES(glFenceSync, "GL_ARB_sync |VERSION_GLES_3"),
GLFUNC_REQUIRES(glGetInteger64v, "GL_ARB_sync |VERSION_GLES_3"),
GLFUNC_REQUIRES(glGetSynciv, "GL_ARB_sync |VERSION_GLES_3"),
GLFUNC_REQUIRES(glIsSync, "GL_ARB_sync |VERSION_GLES_3"),
GLFUNC_REQUIRES(glWaitSync, "GL_ARB_sync |VERSION_GLES_3"),
// ARB_texture_multisample
GLFUNC_REQUIRES(glTexImage2DMultisample, "GL_ARB_texture_multisample"),
GLFUNC_REQUIRES(glTexImage3DMultisample, "GL_ARB_texture_multisample"),
GLFUNC_REQUIRES(glGetMultisamplefv, "GL_ARB_texture_multisample"),
GLFUNC_REQUIRES(glSampleMaski, "GL_ARB_texture_multisample"),
// ARB_texture_multisample
GLFUNC_REQUIRES(glTexImage2DMultisample, "GL_ARB_texture_multisample"),
GLFUNC_REQUIRES(glTexImage3DMultisample, "GL_ARB_texture_multisample"),
GLFUNC_REQUIRES(glGetMultisamplefv, "GL_ARB_texture_multisample"),
GLFUNC_REQUIRES(glSampleMaski, "GL_ARB_texture_multisample"),
// ARB_texture_storage_multisample
GLFUNC_REQUIRES(glTexStorage2DMultisample,
"GL_ARB_texture_storage_multisample !VERSION_4_3 |VERSION_GLES_3_1"),
GLFUNC_REQUIRES(glTexStorage3DMultisample,
"GL_ARB_texture_storage_multisample !VERSION_4_3 |VERSION_GLES_3_2"),
GLFUNC_SUFFIX(glTexStorage3DMultisample, OES,
"GL_OES_texture_storage_multisample_2d_array !VERSION_GLES_3_2"),
// ARB_texture_storage
GLFUNC_REQUIRES(glTexStorage1D, "GL_ARB_texture_storage !VERSION_4_2"),
GLFUNC_REQUIRES(glTexStorage2D, "GL_ARB_texture_storage !VERSION_4_2 |VERSION_GLES_3"),
GLFUNC_REQUIRES(glTexStorage3D, "GL_ARB_texture_storage !VERSION_4_2 |VERSION_GLES_3"),
// ARB_ES2_compatibility
GLFUNC_REQUIRES(glClearDepthf, "GL_ARB_ES2_compatibility |VERSION_GLES_2"),
GLFUNC_REQUIRES(glDepthRangef, "GL_ARB_ES2_compatibility |VERSION_GLES_2"),
GLFUNC_REQUIRES(glGetShaderPrecisionFormat, "GL_ARB_ES2_compatibility |VERSION_GLES_2"),
GLFUNC_REQUIRES(glReleaseShaderCompiler, "GL_ARB_ES2_compatibility |VERSION_GLES_2"),
GLFUNC_REQUIRES(glShaderBinary, "GL_ARB_ES2_compatibility |VERSION_GLES_2"),
// ARB_texture_storage_multisample
GLFUNC_REQUIRES(glTexStorage2DMultisample,
"GL_ARB_texture_storage_multisample !VERSION_4_3 |VERSION_GLES_3_1"),
GLFUNC_REQUIRES(glTexStorage3DMultisample,
"GL_ARB_texture_storage_multisample !VERSION_4_3 |VERSION_GLES_3_2"),
GLFUNC_SUFFIX(glTexStorage3DMultisample, OES,
"GL_OES_texture_storage_multisample_2d_array !VERSION_GLES_3_2"),
// NV_primitive_restart
GLFUNC_REQUIRES(glPrimitiveRestartIndexNV, "GL_NV_primitive_restart"),
GLFUNC_REQUIRES(glPrimitiveRestartNV, "GL_NV_primitive_restart"),
// ARB_ES2_compatibility
GLFUNC_REQUIRES(glClearDepthf, "GL_ARB_ES2_compatibility |VERSION_GLES_2"),
GLFUNC_REQUIRES(glDepthRangef, "GL_ARB_ES2_compatibility |VERSION_GLES_2"),
GLFUNC_REQUIRES(glGetShaderPrecisionFormat, "GL_ARB_ES2_compatibility |VERSION_GLES_2"),
GLFUNC_REQUIRES(glReleaseShaderCompiler, "GL_ARB_ES2_compatibility |VERSION_GLES_2"),
GLFUNC_REQUIRES(glShaderBinary, "GL_ARB_ES2_compatibility |VERSION_GLES_2"),
// ARB_blend_func_extended
GLFUNC_REQUIRES(glBindFragDataLocationIndexed, "GL_ARB_blend_func_extended"),
GLFUNC_REQUIRES(glGetFragDataIndex, "GL_ARB_blend_func_extended"),
// NV_primitive_restart
GLFUNC_REQUIRES(glPrimitiveRestartIndexNV, "GL_NV_primitive_restart"),
GLFUNC_REQUIRES(glPrimitiveRestartNV, "GL_NV_primitive_restart"),
// ARB_viewport_array
GLFUNC_REQUIRES(glDepthRangeArrayv, "GL_ARB_viewport_array"),
GLFUNC_REQUIRES(glDepthRangeIndexed, "GL_ARB_viewport_array"),
GLFUNC_REQUIRES(glGetDoublei_v, "GL_ARB_viewport_array"),
GLFUNC_REQUIRES(glGetFloati_v, "GL_ARB_viewport_array"),
GLFUNC_REQUIRES(glScissorArrayv, "GL_ARB_viewport_array"),
GLFUNC_REQUIRES(glScissorIndexed, "GL_ARB_viewport_array"),
GLFUNC_REQUIRES(glScissorIndexedv, "GL_ARB_viewport_array"),
GLFUNC_REQUIRES(glViewportArrayv, "GL_ARB_viewport_array"),
GLFUNC_REQUIRES(glViewportIndexedf, "GL_ARB_viewport_array"),
GLFUNC_REQUIRES(glViewportIndexedfv, "GL_ARB_viewport_array"),
// ARB_blend_func_extended
GLFUNC_REQUIRES(glBindFragDataLocationIndexed, "GL_ARB_blend_func_extended"),
GLFUNC_REQUIRES(glGetFragDataIndex, "GL_ARB_blend_func_extended"),
// ARB_draw_elements_base_vertex
GLFUNC_REQUIRES(glDrawElementsBaseVertex, "GL_ARB_draw_elements_base_vertex |VERSION_GLES_3_2"),
GLFUNC_REQUIRES(glDrawElementsInstancedBaseVertex,
"GL_ARB_draw_elements_base_vertex |VERSION_GLES_3_2"),
GLFUNC_REQUIRES(glDrawRangeElementsBaseVertex,
"GL_ARB_draw_elements_base_vertex |VERSION_GLES_3_2"),
GLFUNC_REQUIRES(glMultiDrawElementsBaseVertex, "GL_ARB_draw_elements_base_vertex"),
// ARB_viewport_array
GLFUNC_REQUIRES(glDepthRangeArrayv, "GL_ARB_viewport_array"),
GLFUNC_REQUIRES(glDepthRangeIndexed, "GL_ARB_viewport_array"),
GLFUNC_REQUIRES(glGetDoublei_v, "GL_ARB_viewport_array"),
GLFUNC_REQUIRES(glGetFloati_v, "GL_ARB_viewport_array"),
GLFUNC_REQUIRES(glScissorArrayv, "GL_ARB_viewport_array"),
GLFUNC_REQUIRES(glScissorIndexed, "GL_ARB_viewport_array"),
GLFUNC_REQUIRES(glScissorIndexedv, "GL_ARB_viewport_array"),
GLFUNC_REQUIRES(glViewportArrayv, "GL_ARB_viewport_array"),
GLFUNC_REQUIRES(glViewportIndexedf, "GL_ARB_viewport_array"),
GLFUNC_REQUIRES(glViewportIndexedfv, "GL_ARB_viewport_array"),
// OES_draw_elements_base_vertex
GLFUNC_SUFFIX(glDrawElementsBaseVertex, OES,
"GL_OES_draw_elements_base_vertex !VERSION_GLES_3_2"),
GLFUNC_SUFFIX(glDrawElementsInstancedBaseVertex, OES,
"GL_OES_draw_elements_base_vertex VERSION_GLES_3 !VERSION_GLES_3_2"),
GLFUNC_SUFFIX(glDrawRangeElementsBaseVertex, OES,
"GL_OES_draw_elements_base_vertex VERSION_GLES_3 !VERSION_GLES_3_2"),
GLFUNC_SUFFIX(glMultiDrawElementsBaseVertex, OES,
"GL_OES_draw_elements_base_vertex GL_EXT_multi_draw_arrays"),
// ARB_draw_elements_base_vertex
GLFUNC_REQUIRES(glDrawElementsBaseVertex, "GL_ARB_draw_elements_base_vertex |VERSION_GLES_3_2"),
GLFUNC_REQUIRES(glDrawElementsInstancedBaseVertex,
"GL_ARB_draw_elements_base_vertex |VERSION_GLES_3_2"),
GLFUNC_REQUIRES(glDrawRangeElementsBaseVertex,
"GL_ARB_draw_elements_base_vertex |VERSION_GLES_3_2"),
GLFUNC_REQUIRES(glMultiDrawElementsBaseVertex, "GL_ARB_draw_elements_base_vertex"),
// EXT_draw_elements_base_vertex
GLFUNC_SUFFIX(
glDrawElementsBaseVertex, EXT,
"GL_EXT_draw_elements_base_vertex !GL_OES_draw_elements_base_vertex !VERSION_GLES_3_2"),
GLFUNC_SUFFIX(glDrawElementsInstancedBaseVertex, EXT,
"GL_EXT_draw_elements_base_vertex VERSION_GLES_3 "
"!GL_OES_draw_elements_base_vertex !VERSION_GLES_3_2"),
GLFUNC_SUFFIX(glDrawRangeElementsBaseVertex, EXT,
"GL_EXT_draw_elements_base_vertex VERSION_GLES_3 "
"!GL_OES_draw_elements_base_vertex !VERSION_GLES_3_2"),
GLFUNC_SUFFIX(glMultiDrawElementsBaseVertex, EXT,
"GL_EXT_draw_elements_base_vertex GL_EXT_multi_draw_arrays "
"!GL_OES_draw_elements_base_vertex !VERSION_GLES_3_2"),
// OES_draw_elements_base_vertex
GLFUNC_SUFFIX(glDrawElementsBaseVertex, OES,
"GL_OES_draw_elements_base_vertex !VERSION_GLES_3_2"),
GLFUNC_SUFFIX(glDrawElementsInstancedBaseVertex, OES,
"GL_OES_draw_elements_base_vertex VERSION_GLES_3 !VERSION_GLES_3_2"),
GLFUNC_SUFFIX(glDrawRangeElementsBaseVertex, OES,
"GL_OES_draw_elements_base_vertex VERSION_GLES_3 !VERSION_GLES_3_2"),
GLFUNC_SUFFIX(glMultiDrawElementsBaseVertex, OES,
"GL_OES_draw_elements_base_vertex GL_EXT_multi_draw_arrays"),
// EXT_draw_elements_base_vertex
GLFUNC_SUFFIX(
glDrawElementsBaseVertex, EXT,
"GL_EXT_draw_elements_base_vertex !GL_OES_draw_elements_base_vertex !VERSION_GLES_3_2"),
GLFUNC_SUFFIX(glDrawElementsInstancedBaseVertex, EXT,
"GL_EXT_draw_elements_base_vertex VERSION_GLES_3 "
"!GL_OES_draw_elements_base_vertex !VERSION_GLES_3_2"),
GLFUNC_SUFFIX(glDrawRangeElementsBaseVertex, EXT,
"GL_EXT_draw_elements_base_vertex VERSION_GLES_3 "
"!GL_OES_draw_elements_base_vertex !VERSION_GLES_3_2"),
GLFUNC_SUFFIX(glMultiDrawElementsBaseVertex, EXT,
"GL_EXT_draw_elements_base_vertex GL_EXT_multi_draw_arrays "
"!GL_OES_draw_elements_base_vertex !VERSION_GLES_3_2"),
// ARB_sample_shading
GLFUNC_SUFFIX(glMinSampleShading, ARB, "GL_ARB_sample_shading"),
@@ -1768,34 +1784,34 @@ const GLFunc gl_function_array[] = {
GLFUNC_SUFFIX(glPopDebugGroup, KHR, "GL_KHR_debug VERSION_GLES_3"),
GLFUNC_SUFFIX(glPushDebugGroup, KHR, "GL_KHR_debug VERSION_GLES_3"),
GLFUNC_REQUIRES(glDebugMessageCallback,
"GL_KHR_debug !VERSION_GLES_3 !VERSION_GL_4_3 |VERSION_GLES_3_2"),
"GL_KHR_debug !VERSION_GLES_3 !VERSION_GL_4_3 |VERSION_GLES_3_2"),
GLFUNC_REQUIRES(glDebugMessageControl,
"GL_KHR_debug !VERSION_GLES_3 !VERSION_GL_4_3 |VERSION_GLES_3_2"),
"GL_KHR_debug !VERSION_GLES_3 !VERSION_GL_4_3 |VERSION_GLES_3_2"),
GLFUNC_REQUIRES(glDebugMessageInsert,
"GL_KHR_debug !VERSION_GLES_3 !VERSION_GL_4_3 |VERSION_GLES_3_2"),
"GL_KHR_debug !VERSION_GLES_3 !VERSION_GL_4_3 |VERSION_GLES_3_2"),
GLFUNC_REQUIRES(glGetDebugMessageLog,
"GL_KHR_debug !VERSION_GLES_3 !VERSION_GL_4_3 |VERSION_GLES_3_2"),
"GL_KHR_debug !VERSION_GLES_3 !VERSION_GL_4_3 |VERSION_GLES_3_2"),
GLFUNC_REQUIRES(glGetObjectLabel,
"GL_KHR_debug !VERSION_GLES_3 !VERSION_GL_4_3 |VERSION_GLES_3_2"),
"GL_KHR_debug !VERSION_GLES_3 !VERSION_GL_4_3 |VERSION_GLES_3_2"),
GLFUNC_REQUIRES(glGetObjectPtrLabel,
"GL_KHR_debug !VERSION_GLES_3 !VERSION_GL_4_3 |VERSION_GLES_3_2"),
"GL_KHR_debug !VERSION_GLES_3 !VERSION_GL_4_3 |VERSION_GLES_3_2"),
GLFUNC_REQUIRES(glObjectLabel,
"GL_KHR_debug !VERSION_GLES_3 !VERSION_GL_4_3 |VERSION_GLES_3_2"),
"GL_KHR_debug !VERSION_GLES_3 !VERSION_GL_4_3 |VERSION_GLES_3_2"),
GLFUNC_REQUIRES(glObjectPtrLabel,
"GL_KHR_debug !VERSION_GLES_3 !VERSION_GL_4_3 |VERSION_GLES_3_2"),
"GL_KHR_debug !VERSION_GLES_3 !VERSION_GL_4_3 |VERSION_GLES_3_2"),
GLFUNC_REQUIRES(glPopDebugGroup,
"GL_KHR_debug !VERSION_GLES_3 !VERSION_GL_4_3 |VERSION_GLES_3_2"),
"GL_KHR_debug !VERSION_GLES_3 !VERSION_GL_4_3 |VERSION_GLES_3_2"),
GLFUNC_REQUIRES(glPushDebugGroup,
"GL_KHR_debug !VERSION_GLES_3 !VERSION_GL_4_3 |VERSION_GLES_3_2"),
"GL_KHR_debug !VERSION_GLES_3 !VERSION_GL_4_3 |VERSION_GLES_3_2"),
// ARB_buffer_storage
GLFUNC_REQUIRES(glBufferStorage, "GL_ARB_buffer_storage !VERSION_4_4"),
GLFUNC_SUFFIX(glNamedBufferStorage, EXT,
"GL_ARB_buffer_storage GL_EXT_direct_state_access !VERSION_4_5"),
"GL_ARB_buffer_storage GL_EXT_direct_state_access !VERSION_4_5"),
// EXT_buffer_storage
GLFUNC_SUFFIX(glBufferStorage, EXT,
"GL_EXT_buffer_storage !GL_ARB_buffer_storage !VERSION_4_4"),
"GL_EXT_buffer_storage !GL_ARB_buffer_storage !VERSION_4_4"),
// EXT_geometry_shader
GLFUNC_SUFFIX(glFramebufferTexture, EXT, "GL_EXT_geometry_shader !VERSION_3_2"),
@@ -1823,14 +1839,14 @@ const GLFunc gl_function_array[] = {
// EXT_copy_image
GLFUNC_SUFFIX(glCopyImageSubData, EXT,
"GL_EXT_copy_image !GL_OES_copy_image !VERSION_GLES_3_2"),
"GL_EXT_copy_image !GL_OES_copy_image !VERSION_GLES_3_2"),
// EXT_texture_buffer
GLFUNC_SUFFIX(glTexBuffer, OES, "GL_OES_texture_buffer !VERSION_GLES_3_2"),
// EXT_texture_buffer
GLFUNC_SUFFIX(glTexBuffer, EXT,
"GL_EXT_texture_buffer !GL_OES_texture_buffer !VERSION_GLES_3_2"),
"GL_EXT_texture_buffer !GL_OES_texture_buffer !VERSION_GLES_3_2"),
// EXT_blend_func_extended
GLFUNC_SUFFIX(glBindFragDataLocationIndexed, EXT, "GL_EXT_blend_func_extended"),
@@ -1838,6 +1854,22 @@ const GLFunc gl_function_array[] = {
// ARB_shader_storage_buffer_object
GLFUNC_REQUIRES(glShaderStorageBlockBinding, "ARB_shader_storage_buffer_object !VERSION_4_3"),
// NV_depth_buffer_float
GLFUNC_REQUIRES(glDepthRangedNV, "GL_NV_depth_buffer_float"),
GLFUNC_REQUIRES(glClearDepthdNV, "GL_NV_depth_buffer_float"),
GLFUNC_REQUIRES(glDepthBoundsdNV, "GL_NV_depth_buffer_float"),
// ARB_shader_image_load_store
GLFUNC_REQUIRES(glBindImageTexture,
"GL_ARB_shader_image_load_store !VERSION_4_2 |VERSION_GLES_3_1"),
GLFUNC_REQUIRES(glMemoryBarrier,
"GL_ARB_shader_image_load_store !VERSION_4_2 |VERSION_GLES_3_1"),
// ARB_compute_shader
GLFUNC_REQUIRES(glDispatchCompute, "GL_ARB_compute_shader !VERSION_4_3 |VERSION_GLES_3_1"),
GLFUNC_REQUIRES(glDispatchComputeIndirect,
"GL_ARB_compute_shader !VERSION_4_3 |VERSION_GLES_3_1"),
};
namespace GLExtensions
@@ -1895,17 +1927,17 @@ static void InitExtensionList()
case 450:
{
std::string gl450exts[] = {
"GL_ARB_ES3_1_compatibility",
"GL_ARB_clip_control",
"GL_ARB_conditional_render_inverted",
"GL_ARB_cull_distance",
"GL_ARB_derivative_control",
"GL_ARB_direct_state_access",
"GL_ARB_get_texture_sub_image",
"GL_ARB_robustness",
"GL_ARB_shader_texture_image_samples",
"GL_ARB_texture_barrier",
"VERSION_4_5",
"GL_ARB_ES3_1_compatibility",
"GL_ARB_clip_control",
"GL_ARB_conditional_render_inverted",
"GL_ARB_cull_distance",
"GL_ARB_derivative_control",
"GL_ARB_direct_state_access",
"GL_ARB_get_texture_sub_image",
"GL_ARB_robustness",
"GL_ARB_shader_texture_image_samples",
"GL_ARB_texture_barrier",
"VERSION_4_5",
};
for (auto it : gl450exts)
m_extension_list[it] = true;
@@ -1913,15 +1945,15 @@ static void InitExtensionList()
case 440:
{
std::string gl440exts[] = {
"GL_ARB_buffer_storage",
"GL_ARB_clear_texture",
"GL_ARB_enhanced_layouts",
"GL_ARB_multi_bind",
"GL_ARB_query_buffer_object",
"GL_ARB_texture_mirror_clamp_to_edge",
"GL_ARB_texture_stencil8",
"GL_ARB_vertex_type_10f_11f_11f_rev",
"VERSION_4_4",
"GL_ARB_buffer_storage",
"GL_ARB_clear_texture",
"GL_ARB_enhanced_layouts",
"GL_ARB_multi_bind",
"GL_ARB_query_buffer_object",
"GL_ARB_texture_mirror_clamp_to_edge",
"GL_ARB_texture_stencil8",
"GL_ARB_vertex_type_10f_11f_11f_rev",
"VERSION_4_4",
};
for (auto it : gl440exts)
m_extension_list[it] = true;
@@ -1929,27 +1961,27 @@ static void InitExtensionList()
case 430:
{
std::string gl430exts[] = {
"GL_ARB_ES3_compatibility",
"GL_ARB_arrays_of_arrays",
"GL_ARB_clear_buffer_object",
"GL_ARB_compute_shader",
"GL_ARB_copy_image",
"GL_ARB_explicit_uniform_location",
"GL_ARB_fragment_layer_viewport",
"GL_ARB_framebuffer_no_attachments",
"GL_ARB_internalformat_query2",
"GL_ARB_invalidate_subdata",
"GL_ARB_multi_draw_indirect",
"GL_ARB_program_interface_query",
"GL_ARB_shader_image_size",
"GL_ARB_shader_storage_buffer_object",
"GL_ARB_stencil_texturing",
"GL_ARB_texture_buffer_range",
"GL_ARB_texture_query_levels",
"GL_ARB_texture_storage_multisample",
"GL_ARB_texture_view",
"GL_ARB_vertex_attrib_binding",
"VERSION_4_3",
"GL_ARB_ES3_compatibility",
"GL_ARB_arrays_of_arrays",
"GL_ARB_clear_buffer_object",
"GL_ARB_compute_shader",
"GL_ARB_copy_image",
"GL_ARB_explicit_uniform_location",
"GL_ARB_fragment_layer_viewport",
"GL_ARB_framebuffer_no_attachments",
"GL_ARB_internalformat_query2",
"GL_ARB_invalidate_subdata",
"GL_ARB_multi_draw_indirect",
"GL_ARB_program_interface_query",
"GL_ARB_shader_image_size",
"GL_ARB_shader_storage_buffer_object",
"GL_ARB_stencil_texturing",
"GL_ARB_texture_buffer_range",
"GL_ARB_texture_query_levels",
"GL_ARB_texture_storage_multisample",
"GL_ARB_texture_view",
"GL_ARB_vertex_attrib_binding",
"VERSION_4_3",
};
for (auto it : gl430exts)
m_extension_list[it] = true;
@@ -1957,19 +1989,19 @@ static void InitExtensionList()
case 420:
{
std::string gl420exts[] = {
"GL_ARB_base_instance",
"GL_ARB_compressed_texture_pixel_storage",
"GL_ARB_conservative_depth",
"GL_ARB_internalformat_query",
"GL_ARB_map_buffer_alignment",
"GL_ARB_shader_atomic_counters",
"GL_ARB_shader_image_load_store",
"GL_ARB_shading_language_420pack",
"GL_ARB_shading_language_packing",
"GL_ARB_texture_compression_BPTC",
"GL_ARB_texture_storage",
"GL_ARB_transform_feedback_instanced",
"VERSION_4_2",
"GL_ARB_base_instance",
"GL_ARB_compressed_texture_pixel_storage",
"GL_ARB_conservative_depth",
"GL_ARB_internalformat_query",
"GL_ARB_map_buffer_alignment",
"GL_ARB_shader_atomic_counters",
"GL_ARB_shader_image_load_store",
"GL_ARB_shading_language_420pack",
"GL_ARB_shading_language_packing",
"GL_ARB_texture_compression_BPTC",
"GL_ARB_texture_storage",
"GL_ARB_transform_feedback_instanced",
"VERSION_4_2",
};
for (auto it : gl420exts)
m_extension_list[it] = true;
@@ -1977,13 +2009,13 @@ static void InitExtensionList()
case 410:
{
std::string gl410exts[] = {
"GL_ARB_ES2_compatibility",
"GL_ARB_get_program_binary",
"GL_ARB_separate_shader_objects",
"GL_ARB_shader_precision",
"GL_ARB_vertex_attrib_64_bit",
"GL_ARB_viewport_array",
"VERSION_4_1",
"GL_ARB_ES2_compatibility",
"GL_ARB_get_program_binary",
"GL_ARB_separate_shader_objects",
"GL_ARB_shader_precision",
"GL_ARB_vertex_attrib_64_bit",
"GL_ARB_viewport_array",
"VERSION_4_1",
};
for (auto it : gl410exts)
m_extension_list[it] = true;
@@ -1991,19 +2023,19 @@ static void InitExtensionList()
case 400:
{
std::string gl400exts[] = {
"GL_ARB_draw_indirect",
"GL_ARB_gpu_shader5",
"GL_ARB_gpu_shader_fp64",
"GL_ARB_sample_shading",
"GL_ARB_shader_subroutine",
"GL_ARB_tessellation_shader",
"GL_ARB_texture_buffer_object_rgb32",
"GL_ARB_texture_cube_map_array",
"GL_ARB_texture_gather",
"GL_ARB_texture_query_lod",
"GL_ARB_transform_feedback2",
"GL_ARB_transform_feedback3",
"VERSION_4_0",
"GL_ARB_draw_indirect",
"GL_ARB_gpu_shader5",
"GL_ARB_gpu_shader_fp64",
"GL_ARB_sample_shading",
"GL_ARB_shader_subroutine",
"GL_ARB_tessellation_shader",
"GL_ARB_texture_buffer_object_rgb32",
"GL_ARB_texture_cube_map_array",
"GL_ARB_texture_gather",
"GL_ARB_texture_query_lod",
"GL_ARB_transform_feedback2",
"GL_ARB_transform_feedback3",
"VERSION_4_0",
};
for (auto it : gl400exts)
m_extension_list[it] = true;
@@ -2011,17 +2043,17 @@ static void InitExtensionList()
case 330:
{
std::string gl330exts[] = {
"GL_ARB_shader_bit_encoding",
"GL_ARB_blend_func_extended",
"GL_ARB_explicit_attrib_location",
"GL_ARB_occlusion_query2",
"GL_ARB_sampler_objects",
"GL_ARB_texture_swizzle",
"GL_ARB_timer_query",
"GL_ARB_instanced_arrays",
"GL_ARB_texture_rgb10_a2ui",
"GL_ARB_vertex_type_2_10_10_10_rev",
"VERSION_3_3",
"GL_ARB_shader_bit_encoding",
"GL_ARB_blend_func_extended",
"GL_ARB_explicit_attrib_location",
"GL_ARB_occlusion_query2",
"GL_ARB_sampler_objects",
"GL_ARB_texture_swizzle",
"GL_ARB_timer_query",
"GL_ARB_instanced_arrays",
"GL_ARB_texture_rgb10_a2ui",
"GL_ARB_vertex_type_2_10_10_10_rev",
"VERSION_3_3",
};
for (auto it : gl330exts)
m_extension_list[it] = true;
@@ -2029,16 +2061,16 @@ static void InitExtensionList()
case 320:
{
std::string gl320exts[] = {
"GL_ARB_geometry_shader4",
"GL_ARB_sync",
"GL_ARB_vertex_array_bgra",
"GL_ARB_draw_elements_base_vertex",
"GL_ARB_seamless_cube_map",
"GL_ARB_texture_multisample",
"GL_ARB_fragment_coord_conventions",
"GL_ARB_provoking_vertex",
"GL_ARB_depth_clamp",
"VERSION_3_2",
"GL_ARB_geometry_shader4",
"GL_ARB_sync",
"GL_ARB_vertex_array_bgra",
"GL_ARB_draw_elements_base_vertex",
"GL_ARB_seamless_cube_map",
"GL_ARB_texture_multisample",
"GL_ARB_fragment_coord_conventions",
"GL_ARB_provoking_vertex",
"GL_ARB_depth_clamp",
"VERSION_3_2",
};
for (auto it : gl320exts)
m_extension_list[it] = true;
@@ -2047,10 +2079,10 @@ static void InitExtensionList()
{
// Can't add NV_primitive_restart since function name changed
std::string gl310exts[] = {
"GL_ARB_draw_instanced", "GL_ARB_copy_buffer", "GL_ARB_texture_buffer_object",
"GL_ARB_texture_rectangle", "GL_ARB_uniform_buffer_object",
//"GL_NV_primitive_restart",
"VERSION_3_1",
"GL_ARB_draw_instanced", "GL_ARB_copy_buffer", "GL_ARB_texture_buffer_object",
"GL_ARB_texture_rectangle", "GL_ARB_uniform_buffer_object",
//"GL_NV_primitive_restart",
"VERSION_3_1",
};
for (auto it : gl310exts)
m_extension_list[it] = true;
@@ -2060,28 +2092,23 @@ static void InitExtensionList()
// Quite a lot of these had their names changed when merged in to core
// Disable the ones that have
std::string gl300exts[] = {
"GL_ARB_map_buffer_range",
//"GL_EXT_gpu_shader4",
//"GL_APPLE_flush_buffer_range",
"GL_ARB_color_buffer_float",
//"GL_NV_depth_buffer_float",
"GL_ARB_texture_float",
//"GL_EXT_packed_float",
//"GL_EXT_texture_shared_exponent",
"GL_ARB_half_float_pixel",
//"GL_NV_half_float",
"GL_ARB_framebuffer_object",
//"GL_EXT_framebuffer_sRGB",
"GL_ARB_texture_float",
//"GL_EXT_texture_integer",
//"GL_EXT_draw_buffers2",
//"GL_EXT_texture_integer",
//"GL_EXT_texture_array",
//"GL_EXT_texture_compression_rgtc",
//"GL_EXT_transform_feedback",
"GL_ARB_vertex_array_object",
//"GL_NV_conditional_render",
"VERSION_3_0",
"GL_ARB_map_buffer_range", "GL_ARB_color_buffer_float", "GL_ARB_texture_float",
"GL_ARB_half_float_pixel", "GL_ARB_framebuffer_object", "GL_ARB_texture_float",
"GL_ARB_vertex_array_object", "GL_ARB_depth_buffer_float",
//"GL_EXT_texture_integer",
//"GL_EXT_gpu_shader4",
//"GL_APPLE_flush_buffer_range",
//"GL_EXT_packed_float",
//"GL_EXT_texture_shared_exponent",
//"GL_NV_half_float",
//"GL_EXT_framebuffer_sRGB",
//"GL_EXT_draw_buffers2",
//"GL_EXT_texture_integer",
//"GL_EXT_texture_array",
//"GL_EXT_texture_compression_rgtc",
//"GL_EXT_transform_feedback",
//"GL_NV_conditional_render",
"VERSION_3_0",
};
for (auto it : gl300exts)
m_extension_list[it] = true;

View File

@@ -12,6 +12,7 @@
#include "Common/GL/GLExtensions/ARB_blend_func_extended.h"
#include "Common/GL/GLExtensions/ARB_buffer_storage.h"
#include "Common/GL/GLExtensions/ARB_clip_control.h"
#include "Common/GL/GLExtensions/ARB_compute_shader.h"
#include "Common/GL/GLExtensions/ARB_copy_image.h"
#include "Common/GL/GLExtensions/ARB_debug_output.h"
#include "Common/GL/GLExtensions/ARB_draw_elements_base_vertex.h"
@@ -21,16 +22,20 @@
#include "Common/GL/GLExtensions/ARB_occlusion_query2.h"
#include "Common/GL/GLExtensions/ARB_sample_shading.h"
#include "Common/GL/GLExtensions/ARB_sampler_objects.h"
#include "Common/GL/GLExtensions/ARB_shader_image_load_store.h"
#include "Common/GL/GLExtensions/ARB_shader_storage_buffer_object.h"
#include "Common/GL/GLExtensions/ARB_sync.h"
#include "Common/GL/GLExtensions/ARB_texture_multisample.h"
#include "Common/GL/GLExtensions/ARB_texture_storage.h"
#include "Common/GL/GLExtensions/ARB_texture_storage_multisample.h"
#include "Common/GL/GLExtensions/ARB_uniform_buffer_object.h"
#include "Common/GL/GLExtensions/ARB_vertex_array_object.h"
#include "Common/GL/GLExtensions/ARB_viewport_array.h"
#include "Common/GL/GLExtensions/EXT_texture_compression_s3tc.h"
#include "Common/GL/GLExtensions/EXT_texture_filter_anisotropic.h"
#include "Common/GL/GLExtensions/HP_occlusion_test.h"
#include "Common/GL/GLExtensions/KHR_debug.h"
#include "Common/GL/GLExtensions/NV_depth_buffer_float.h"
#include "Common/GL/GLExtensions/NV_occlusion_query_samples.h"
#include "Common/GL/GLExtensions/NV_primitive_restart.h"
#include "Common/GL/GLExtensions/gl_1_1.h"

View File

@@ -0,0 +1,41 @@
/*
** Copyright (c) 2013-2015 The Khronos Group Inc.
**
** Permission is hereby granted, free of charge, to any person obtaining a
** copy of this software and/or associated documentation files (the
** "Materials"), to deal in the Materials without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Materials, and to
** permit persons to whom the Materials are furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be included
** in all copies or substantial portions of the Materials.
**
** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
*/
#include "Common/GL/GLExtensions/gl_common.h"
#define GL_DEPTH_COMPONENT32F_NV 0x8DAB
#define GL_DEPTH32F_STENCIL8_NV 0x8DAC
#define GL_FLOAT_32_UNSIGNED_INT_24_8_REV_NV 0x8DAD
#define GL_DEPTH_BUFFER_FLOAT_MODE_NV 0x8DAF
typedef void(APIENTRYP PFNDOLDEPTHRANGEDNVPROC)(GLdouble zNear, GLdouble zFar);
typedef void(APIENTRYP PFNDOLCLEARDEPTHDNVPROC)(GLdouble depth);
typedef void(APIENTRYP PFNDOLDEPTHBOUNDSDNVPROC)(GLdouble zmin, GLdouble zmax);
extern PFNDOLDEPTHRANGEDNVPROC dolDepthRangedNV;
extern PFNDOLCLEARDEPTHDNVPROC dolClearDepthdNV;
extern PFNDOLDEPTHBOUNDSDNVPROC dolDepthBoundsdNV;
#define glDepthRangedNV dolDepthRangedNV
#define glClearDepthdNV dolClearDepthdNV
#define glDepthBoundsdNV dolDepthBoundsdNV

View File

@@ -66,75 +66,10 @@
#define GL_ACTIVE_ATOMIC_COUNTER_BUFFERS 0x92D9
#define GL_UNIFORM_ATOMIC_COUNTER_BUFFER_INDEX 0x92DA
#define GL_UNSIGNED_INT_ATOMIC_COUNTER 0x92DB
#define GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT 0x00000001
#define GL_ELEMENT_ARRAY_BARRIER_BIT 0x00000002
#define GL_UNIFORM_BARRIER_BIT 0x00000004
#define GL_TEXTURE_FETCH_BARRIER_BIT 0x00000008
#define GL_SHADER_IMAGE_ACCESS_BARRIER_BIT 0x00000020
#define GL_COMMAND_BARRIER_BIT 0x00000040
#define GL_PIXEL_BUFFER_BARRIER_BIT 0x00000080
#define GL_TEXTURE_UPDATE_BARRIER_BIT 0x00000100
#define GL_BUFFER_UPDATE_BARRIER_BIT 0x00000200
#define GL_FRAMEBUFFER_BARRIER_BIT 0x00000400
#define GL_TRANSFORM_FEEDBACK_BARRIER_BIT 0x00000800
#define GL_ATOMIC_COUNTER_BARRIER_BIT 0x00001000
#define GL_ALL_BARRIER_BITS 0xFFFFFFFF
#define GL_MAX_IMAGE_UNITS 0x8F38
#define GL_MAX_COMBINED_IMAGE_UNITS_AND_FRAGMENT_OUTPUTS 0x8F39
#define GL_IMAGE_BINDING_NAME 0x8F3A
#define GL_IMAGE_BINDING_LEVEL 0x8F3B
#define GL_IMAGE_BINDING_LAYERED 0x8F3C
#define GL_IMAGE_BINDING_LAYER 0x8F3D
#define GL_IMAGE_BINDING_ACCESS 0x8F3E
#define GL_IMAGE_1D 0x904C
#define GL_IMAGE_2D 0x904D
#define GL_IMAGE_3D 0x904E
#define GL_IMAGE_2D_RECT 0x904F
#define GL_IMAGE_CUBE 0x9050
#define GL_IMAGE_BUFFER 0x9051
#define GL_IMAGE_1D_ARRAY 0x9052
#define GL_IMAGE_2D_ARRAY 0x9053
#define GL_IMAGE_CUBE_MAP_ARRAY 0x9054
#define GL_IMAGE_2D_MULTISAMPLE 0x9055
#define GL_IMAGE_2D_MULTISAMPLE_ARRAY 0x9056
#define GL_INT_IMAGE_1D 0x9057
#define GL_INT_IMAGE_2D 0x9058
#define GL_INT_IMAGE_3D 0x9059
#define GL_INT_IMAGE_2D_RECT 0x905A
#define GL_INT_IMAGE_CUBE 0x905B
#define GL_INT_IMAGE_BUFFER 0x905C
#define GL_INT_IMAGE_1D_ARRAY 0x905D
#define GL_INT_IMAGE_2D_ARRAY 0x905E
#define GL_INT_IMAGE_CUBE_MAP_ARRAY 0x905F
#define GL_INT_IMAGE_2D_MULTISAMPLE 0x9060
#define GL_INT_IMAGE_2D_MULTISAMPLE_ARRAY 0x9061
#define GL_UNSIGNED_INT_IMAGE_1D 0x9062
#define GL_UNSIGNED_INT_IMAGE_2D 0x9063
#define GL_UNSIGNED_INT_IMAGE_3D 0x9064
#define GL_UNSIGNED_INT_IMAGE_2D_RECT 0x9065
#define GL_UNSIGNED_INT_IMAGE_CUBE 0x9066
#define GL_UNSIGNED_INT_IMAGE_BUFFER 0x9067
#define GL_UNSIGNED_INT_IMAGE_1D_ARRAY 0x9068
#define GL_UNSIGNED_INT_IMAGE_2D_ARRAY 0x9069
#define GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY 0x906A
#define GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE 0x906B
#define GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY 0x906C
#define GL_MAX_IMAGE_SAMPLES 0x906D
#define GL_IMAGE_BINDING_FORMAT 0x906E
#define GL_IMAGE_FORMAT_COMPATIBILITY_TYPE 0x90C7
#define GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE 0x90C8
#define GL_IMAGE_FORMAT_COMPATIBILITY_BY_CLASS 0x90C9
#define GL_MAX_VERTEX_IMAGE_UNIFORMS 0x90CA
#define GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS 0x90CB
#define GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS 0x90CC
#define GL_MAX_GEOMETRY_IMAGE_UNIFORMS 0x90CD
#define GL_MAX_FRAGMENT_IMAGE_UNIFORMS 0x90CE
#define GL_MAX_COMBINED_IMAGE_UNIFORMS 0x90CF
#define GL_COMPRESSED_RGBA_BPTC_UNORM 0x8E8C
#define GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM 0x8E8D
#define GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT 0x8E8E
#define GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT 0x8E8F
#define GL_TEXTURE_IMMUTABLE_FORMAT 0x912F
typedef void(APIENTRYP PFNDOLDRAWARRAYSINSTANCEDBASEINSTANCEPROC)(GLenum mode, GLint first,
GLsizei count,
@@ -152,16 +87,6 @@ typedef void(APIENTRYP PFNDOLGETINTERNALFORMATIVPROC)(GLenum target, GLenum inte
GLenum pname, GLsizei bufSize, GLint* params);
typedef void(APIENTRYP PFNDOLGETACTIVEATOMICCOUNTERBUFFERIVPROC)(GLuint program, GLuint bufferIndex,
GLenum pname, GLint* params);
typedef void(APIENTRYP PFNDOLBINDIMAGETEXTUREPROC)(GLuint unit, GLuint texture, GLint level,
GLboolean layered, GLint layer, GLenum access,
GLenum format);
typedef void(APIENTRYP PFNDOLMEMORYBARRIERPROC)(GLbitfield barriers);
typedef void(APIENTRYP PFNDOLTEXSTORAGE1DPROC)(GLenum target, GLsizei levels, GLenum internalformat,
GLsizei width);
typedef void(APIENTRYP PFNDOLTEXSTORAGE2DPROC)(GLenum target, GLsizei levels, GLenum internalformat,
GLsizei width, GLsizei height);
typedef void(APIENTRYP PFNDOLTEXSTORAGE3DPROC)(GLenum target, GLsizei levels, GLenum internalformat,
GLsizei width, GLsizei height, GLsizei depth);
typedef void(APIENTRYP PFNDOLDRAWTRANSFORMFEEDBACKINSTANCEDPROC)(GLenum mode, GLuint id,
GLsizei instancecount);
typedef void(APIENTRYP PFNDOLDRAWTRANSFORMFEEDBACKSTREAMINSTANCEDPROC)(GLenum mode, GLuint id,
@@ -174,11 +99,6 @@ extern PFNDOLDRAWELEMENTSINSTANCEDBASEVERTEXBASEINSTANCEPROC
dolDrawElementsInstancedBaseVertexBaseInstance;
extern PFNDOLGETINTERNALFORMATIVPROC dolGetInternalformativ;
extern PFNDOLGETACTIVEATOMICCOUNTERBUFFERIVPROC dolGetActiveAtomicCounterBufferiv;
extern PFNDOLBINDIMAGETEXTUREPROC dolBindImageTexture;
extern PFNDOLMEMORYBARRIERPROC dolMemoryBarrier;
extern PFNDOLTEXSTORAGE1DPROC dolTexStorage1D;
extern PFNDOLTEXSTORAGE2DPROC dolTexStorage2D;
extern PFNDOLTEXSTORAGE3DPROC dolTexStorage3D;
extern PFNDOLDRAWTRANSFORMFEEDBACKINSTANCEDPROC dolDrawTransformFeedbackInstanced;
extern PFNDOLDRAWTRANSFORMFEEDBACKSTREAMINSTANCEDPROC dolDrawTransformFeedbackStreamInstanced;
@@ -187,10 +107,5 @@ extern PFNDOLDRAWTRANSFORMFEEDBACKSTREAMINSTANCEDPROC dolDrawTransformFeedbackSt
#define glDrawElementsInstancedBaseVertexBaseInstance dolDrawElementsInstancedBaseVertexBaseInstance
#define glGetInternalformativ dolGetInternalformativ
#define glGetActiveAtomicCounterBufferiv dolGetActiveAtomicCounterBufferiv
#define glBindImageTexture dolBindImageTexture
#define glMemoryBarrier dolMemoryBarrier
#define glTexStorage1D dolTexStorage1D
#define glTexStorage2D dolTexStorage2D
#define glTexStorage3D dolTexStorage3D
#define glDrawTransformFeedbackInstanced dolDrawTransformFeedbackInstanced
#define glDrawTransformFeedbackStreamInstanced dolDrawTransformFeedbackStreamInstanced

View File

@@ -38,24 +38,6 @@
#define GL_PRIMITIVE_RESTART_FIXED_INDEX 0x8D69
#define GL_ANY_SAMPLES_PASSED_CONSERVATIVE 0x8D6A
#define GL_MAX_ELEMENT_INDEX 0x8D6B
#define GL_COMPUTE_SHADER 0x91B9
#define GL_MAX_COMPUTE_UNIFORM_BLOCKS 0x91BB
#define GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS 0x91BC
#define GL_MAX_COMPUTE_IMAGE_UNIFORMS 0x91BD
#define GL_MAX_COMPUTE_SHARED_MEMORY_SIZE 0x8262
#define GL_MAX_COMPUTE_UNIFORM_COMPONENTS 0x8263
#define GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS 0x8264
#define GL_MAX_COMPUTE_ATOMIC_COUNTERS 0x8265
#define GL_MAX_COMBINED_COMPUTE_UNIFORM_COMPONENTS 0x8266
#define GL_MAX_COMPUTE_WORK_GROUP_INVOCATIONS 0x90EB
#define GL_MAX_COMPUTE_WORK_GROUP_COUNT 0x91BE
#define GL_MAX_COMPUTE_WORK_GROUP_SIZE 0x91BF
#define GL_COMPUTE_WORK_GROUP_SIZE 0x8267
#define GL_UNIFORM_BLOCK_REFERENCED_BY_COMPUTE_SHADER 0x90EC
#define GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_COMPUTE_SHADER 0x90ED
#define GL_DISPATCH_INDIRECT_BUFFER 0x90EE
#define GL_DISPATCH_INDIRECT_BUFFER_BINDING 0x90EF
#define GL_COMPUTE_SHADER_BIT 0x00000020
#define GL_DEBUG_OUTPUT_SYNCHRONOUS 0x8242
#define GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH 0x8243
#define GL_DEBUG_CALLBACK_FUNCTION 0x8244
@@ -287,9 +269,6 @@ typedef void(APIENTRYP PFNDOLCLEARBUFFERDATAPROC)(GLenum target, GLenum internal
typedef void(APIENTRYP PFNDOLCLEARBUFFERSUBDATAPROC)(GLenum target, GLenum internalformat,
GLintptr offset, GLsizeiptr size,
GLenum format, GLenum type, const void* data);
typedef void(APIENTRYP PFNDOLDISPATCHCOMPUTEPROC)(GLuint num_groups_x, GLuint num_groups_y,
GLuint num_groups_z);
typedef void(APIENTRYP PFNDOLDISPATCHCOMPUTEINDIRECTPROC)(GLintptr indirect);
typedef void(APIENTRYP PFNDOLFRAMEBUFFERPARAMETERIPROC)(GLenum target, GLenum pname, GLint param);
typedef void(APIENTRYP PFNDOLGETFRAMEBUFFERPARAMETERIVPROC)(GLenum target, GLenum pname,
GLint* params);
@@ -348,8 +327,6 @@ typedef void(APIENTRYP PFNDOLVERTEXBINDINGDIVISORPROC)(GLuint bindingindex, GLui
extern PFNDOLCLEARBUFFERDATAPROC dolClearBufferData;
extern PFNDOLCLEARBUFFERSUBDATAPROC dolClearBufferSubData;
extern PFNDOLDISPATCHCOMPUTEPROC dolDispatchCompute;
extern PFNDOLDISPATCHCOMPUTEINDIRECTPROC dolDispatchComputeIndirect;
extern PFNDOLFRAMEBUFFERPARAMETERIPROC dolFramebufferParameteri;
extern PFNDOLGETFRAMEBUFFERPARAMETERIVPROC dolGetFramebufferParameteriv;
extern PFNDOLGETINTERNALFORMATI64VPROC dolGetInternalformati64v;
@@ -378,8 +355,6 @@ extern PFNDOLVERTEXBINDINGDIVISORPROC dolVertexBindingDivisor;
#define glClearBufferData dolClearBufferData
#define glClearBufferSubData dolClearBufferSubData
#define glDispatchCompute dolDispatchCompute
#define glDispatchComputeIndirect dolDispatchComputeIndirect
#define glFramebufferParameteri dolFramebufferParameteri
#define glGetFramebufferParameteriv dolGetFramebufferParameteriv
#define glGetInternalformati64v dolGetInternalformati64v

View File

@@ -0,0 +1,70 @@
// Copyright 2017 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#include "Common/GL/GLInterface/BGL.h"
#include <GLView.h>
#include <Size.h>
#include <Window.h>
void cInterfaceBGL::Swap()
{
m_gl->SwapBuffers();
}
bool cInterfaceBGL::Create(void* window_handle, bool core)
{
m_window = static_cast<BWindow*>(window_handle);
m_gl = new BGLView(m_window->Bounds(), "cInterfaceBGL", B_FOLLOW_ALL_SIDES, 0,
BGL_RGB | BGL_DOUBLE | BGL_ALPHA);
m_window->AddChild(m_gl);
s_opengl_mode = GLInterfaceMode::MODE_OPENGL;
// Control m_window size and picture scaling
BRect size = m_gl->Frame();
s_backbuffer_width = size.IntegerWidth();
s_backbuffer_height = size.IntegerHeight();
return true;
}
bool cInterfaceBGL::MakeCurrent()
{
m_gl->LockGL();
return true;
}
bool cInterfaceBGL::ClearCurrent()
{
m_gl->UnlockGL();
return true;
}
void cInterfaceBGL::Shutdown()
{
// We don't need to delete m_gl, it's owned by the BWindow.
m_gl = nullptr;
}
void cInterfaceBGL::Update()
{
BRect size = m_gl->Frame();
if (s_backbuffer_width == size.IntegerWidth() && s_backbuffer_height == size.IntegerHeight())
return;
s_backbuffer_width = size.IntegerWidth();
s_backbuffer_height = size.IntegerHeight();
}
void cInterfaceBGL::SwapInterval(int interval)
{
}
void* cInterfaceBGL::GetFuncAddress(const std::string& name)
{
return m_gl->GetGLProcAddress(name.c_str());
}

View File

@@ -0,0 +1,27 @@
// Copyright 2017 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#pragma once
#include "Common/GL/GLInterfaceBase.h"
class BWindow;
class BGLView;
class cInterfaceBGL final : public cInterfaceBase
{
public:
void Swap() override;
void* GetFuncAddress(const std::string& name) override;
bool Create(void* window_handle, bool core) override;
bool MakeCurrent() override;
bool ClearCurrent() override;
void Shutdown() override;
void Update() override;
void SwapInterval(int interval) override;
private:
BWindow* m_window;
BGLView* m_gl;
};

View File

@@ -30,348 +30,346 @@
// Show the current FPS
void cInterfaceEGL::Swap()
{
if (egl_surf != EGL_NO_SURFACE)
eglSwapBuffers(egl_dpy, egl_surf);
if (egl_surf != EGL_NO_SURFACE)
eglSwapBuffers(egl_dpy, egl_surf);
}
void cInterfaceEGL::SwapInterval(int Interval)
{
eglSwapInterval(egl_dpy, Interval);
eglSwapInterval(egl_dpy, Interval);
}
void* cInterfaceEGL::GetFuncAddress(const std::string& name)
{
return (void*)eglGetProcAddress(name.c_str());
return (void*)eglGetProcAddress(name.c_str());
}
void cInterfaceEGL::DetectMode()
{
if (s_opengl_mode != GLInterfaceMode::MODE_DETECT)
return;
if (s_opengl_mode != GLInterfaceMode::MODE_DETECT)
return;
EGLint num_configs;
bool supportsGL = false, supportsGLES2 = false, supportsGLES3 = false;
std::array<int, 3> renderable_types = {
EGL_OPENGL_BIT, (1 << 6), /* EGL_OPENGL_ES3_BIT_KHR */
EGL_OPENGL_ES2_BIT,
};
EGLint num_configs;
bool supportsGL = false, supportsGLES2 = false, supportsGLES3 = false;
std::array<int, 3> renderable_types{{
EGL_OPENGL_BIT, (1 << 6), /* EGL_OPENGL_ES3_BIT_KHR */
EGL_OPENGL_ES2_BIT,
}};
for (auto renderable_type : renderable_types)
{
// attributes for a visual in RGBA format with at least
// 8 bits per color
int attribs[] = {
EGL_RED_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_BLUE_SIZE, 8,
EGL_RENDERABLE_TYPE, renderable_type,
EGL_NONE
};
for (auto renderable_type : renderable_types)
{
// attributes for a visual in RGBA format with at least
// 8 bits per color
int attribs[] = {EGL_RED_SIZE, 8, EGL_GREEN_SIZE, 8,
EGL_BLUE_SIZE, 8, EGL_RENDERABLE_TYPE, renderable_type,
EGL_NONE};
// Get how many configs there are
if (!eglChooseConfig(egl_dpy, attribs, nullptr, 0, &num_configs))
{
INFO_LOG(VIDEO, "Error: couldn't get an EGL visual config");
continue;
}
// Get how many configs there are
if (!eglChooseConfig(egl_dpy, attribs, nullptr, 0, &num_configs))
{
INFO_LOG(VIDEO, "Error: couldn't get an EGL visual config");
continue;
}
EGLConfig* config = new EGLConfig[num_configs];
EGLConfig* config = new EGLConfig[num_configs];
// Get all the configurations
if (!eglChooseConfig(egl_dpy, attribs, config, num_configs, &num_configs))
{
INFO_LOG(VIDEO, "Error: couldn't get an EGL visual config");
delete[] config;
continue;
}
// Get all the configurations
if (!eglChooseConfig(egl_dpy, attribs, config, num_configs, &num_configs))
{
INFO_LOG(VIDEO, "Error: couldn't get an EGL visual config");
delete[] config;
continue;
}
for (int i = 0; i < num_configs; ++i)
{
EGLint attribVal;
bool ret;
ret = eglGetConfigAttrib(egl_dpy, config[i], EGL_RENDERABLE_TYPE, &attribVal);
if (ret)
{
if (attribVal & EGL_OPENGL_BIT)
supportsGL = true;
if (attribVal & (1 << 6)) /* EGL_OPENGL_ES3_BIT_KHR */
supportsGLES3 = true;
if (attribVal & EGL_OPENGL_ES2_BIT)
supportsGLES2 = true;
}
}
delete[] config;
}
for (int i = 0; i < num_configs; ++i)
{
EGLint attribVal;
bool ret;
ret = eglGetConfigAttrib(egl_dpy, config[i], EGL_RENDERABLE_TYPE, &attribVal);
if (ret)
{
if (attribVal & EGL_OPENGL_BIT)
supportsGL = true;
if (attribVal & (1 << 6)) /* EGL_OPENGL_ES3_BIT_KHR */
supportsGLES3 = true;
if (attribVal & EGL_OPENGL_ES2_BIT)
supportsGLES2 = true;
}
}
delete[] config;
}
if (supportsGL)
s_opengl_mode = GLInterfaceMode::MODE_OPENGL;
else if (supportsGLES3)
s_opengl_mode = GLInterfaceMode::MODE_OPENGLES3;
else if (supportsGLES2)
s_opengl_mode = GLInterfaceMode::MODE_OPENGLES2;
if (supportsGL)
s_opengl_mode = GLInterfaceMode::MODE_OPENGL;
else if (supportsGLES3)
s_opengl_mode = GLInterfaceMode::MODE_OPENGLES3;
else if (supportsGLES2)
s_opengl_mode = GLInterfaceMode::MODE_OPENGLES2;
if (s_opengl_mode == GLInterfaceMode::MODE_DETECT) // Errored before we found a mode
s_opengl_mode = GLInterfaceMode::MODE_OPENGL; // Fall back to OpenGL
if (s_opengl_mode == GLInterfaceMode::MODE_DETECT) // Errored before we found a mode
s_opengl_mode = GLInterfaceMode::MODE_OPENGL; // Fall back to OpenGL
}
// Create rendering window.
// Call browser: Core.cpp:EmuThread() > main.cpp:Video_Initialize()
bool cInterfaceEGL::Create(void* window_handle, bool core)
{
EGLint egl_major, egl_minor;
bool supports_core_profile = false;
EGLint egl_major, egl_minor;
bool supports_core_profile = false;
egl_dpy = OpenDisplay();
m_host_window = (EGLNativeWindowType)window_handle;
m_has_handle = !!window_handle;
m_core = core;
egl_dpy = OpenDisplay();
m_host_window = (EGLNativeWindowType)window_handle;
m_has_handle = !!window_handle;
m_core = core;
if (!egl_dpy)
{
INFO_LOG(VIDEO, "Error: eglGetDisplay() failed");
return false;
}
if (!egl_dpy)
{
INFO_LOG(VIDEO, "Error: eglGetDisplay() failed");
return false;
}
if (!eglInitialize(egl_dpy, &egl_major, &egl_minor))
{
INFO_LOG(VIDEO, "Error: eglInitialize() failed");
return false;
}
if (!eglInitialize(egl_dpy, &egl_major, &egl_minor))
{
INFO_LOG(VIDEO, "Error: eglInitialize() failed");
return false;
}
/* Detection code */
EGLint num_configs;
/* Detection code */
EGLint num_configs;
DetectMode();
DetectMode();
// attributes for a visual in RGBA format with at least
// 8 bits per color
int attribs[] = {
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
EGL_RED_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_BLUE_SIZE, 8,
EGL_NONE };
// attributes for a visual in RGBA format with at least
// 8 bits per color
int attribs[] = {EGL_RENDERABLE_TYPE,
EGL_OPENGL_ES2_BIT,
EGL_RED_SIZE,
8,
EGL_GREEN_SIZE,
8,
EGL_BLUE_SIZE,
8,
EGL_NONE};
std::vector<EGLint> ctx_attribs;
switch (s_opengl_mode)
{
case GLInterfaceMode::MODE_OPENGL:
attribs[1] = EGL_OPENGL_BIT;
ctx_attribs = { EGL_NONE };
break;
case GLInterfaceMode::MODE_OPENGLES2:
attribs[1] = EGL_OPENGL_ES2_BIT;
ctx_attribs = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
break;
case GLInterfaceMode::MODE_OPENGLES3:
attribs[1] = (1 << 6); /* EGL_OPENGL_ES3_BIT_KHR */
ctx_attribs = { EGL_CONTEXT_CLIENT_VERSION, 3, EGL_NONE };
break;
default:
ERROR_LOG(VIDEO, "Unknown opengl mode set");
return false;
break;
}
std::vector<EGLint> ctx_attribs;
switch (s_opengl_mode)
{
case GLInterfaceMode::MODE_OPENGL:
attribs[1] = EGL_OPENGL_BIT;
ctx_attribs = {EGL_NONE};
break;
case GLInterfaceMode::MODE_OPENGLES2:
attribs[1] = EGL_OPENGL_ES2_BIT;
ctx_attribs = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE};
break;
case GLInterfaceMode::MODE_OPENGLES3:
attribs[1] = (1 << 6); /* EGL_OPENGL_ES3_BIT_KHR */
ctx_attribs = {EGL_CONTEXT_CLIENT_VERSION, 3, EGL_NONE};
break;
default:
ERROR_LOG(VIDEO, "Unknown opengl mode set");
return false;
break;
}
if (!eglChooseConfig(egl_dpy, attribs, &m_config, 1, &num_configs))
{
INFO_LOG(VIDEO, "Error: couldn't get an EGL visual config");
return false;
}
if (!eglChooseConfig(egl_dpy, attribs, &m_config, 1, &num_configs))
{
INFO_LOG(VIDEO, "Error: couldn't get an EGL visual config");
return false;
}
if (s_opengl_mode == GLInterfaceMode::MODE_OPENGL)
eglBindAPI(EGL_OPENGL_API);
else
eglBindAPI(EGL_OPENGL_ES_API);
if (s_opengl_mode == GLInterfaceMode::MODE_OPENGL)
eglBindAPI(EGL_OPENGL_API);
else
eglBindAPI(EGL_OPENGL_ES_API);
std::string tmp;
std::istringstream buffer(eglQueryString(egl_dpy, EGL_EXTENSIONS));
while (buffer >> tmp)
{
if (tmp == "EGL_KHR_surfaceless_context")
m_supports_surfaceless = true;
else if (tmp == "EGL_KHR_create_context")
supports_core_profile = true;
}
std::string tmp;
std::istringstream buffer(eglQueryString(egl_dpy, EGL_EXTENSIONS));
while (buffer >> tmp)
{
if (tmp == "EGL_KHR_surfaceless_context")
m_supports_surfaceless = true;
else if (tmp == "EGL_KHR_create_context")
supports_core_profile = true;
}
if (supports_core_profile && core && s_opengl_mode == GLInterfaceMode::MODE_OPENGL)
{
std::array<std::pair<int, int>, 7> versions_to_try = { {
{4, 5}, {4, 4}, {4, 3}, {4, 2}, {4, 1}, {4, 0}, {3, 3},
} };
if (supports_core_profile && core && s_opengl_mode == GLInterfaceMode::MODE_OPENGL)
{
std::array<std::pair<int, int>, 7> versions_to_try = {{
{4, 5}, {4, 4}, {4, 3}, {4, 2}, {4, 1}, {4, 0}, {3, 3},
}};
for (const auto& version : versions_to_try)
{
std::vector<EGLint> core_attribs =
{
EGL_CONTEXT_MAJOR_VERSION_KHR, version.first,
EGL_CONTEXT_MINOR_VERSION_KHR, version.second,
EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR,
EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR,
EGL_CONTEXT_FLAGS_KHR,
EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR,
EGL_NONE
};
for (const auto& version : versions_to_try)
{
std::vector<EGLint> core_attribs = {EGL_CONTEXT_MAJOR_VERSION_KHR,
version.first,
EGL_CONTEXT_MINOR_VERSION_KHR,
version.second,
EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR,
EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR,
EGL_CONTEXT_FLAGS_KHR,
EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR,
EGL_NONE};
egl_ctx = eglCreateContext(egl_dpy, m_config, EGL_NO_CONTEXT, &core_attribs[0]);
if (egl_ctx)
break;
}
}
egl_ctx = eglCreateContext(egl_dpy, m_config, EGL_NO_CONTEXT, &core_attribs[0]);
if (egl_ctx)
break;
}
}
if (!egl_ctx)
{
m_core = false;
egl_ctx = eglCreateContext(egl_dpy, m_config, EGL_NO_CONTEXT, &ctx_attribs[0]);
}
if (!egl_ctx)
{
m_core = false;
egl_ctx = eglCreateContext(egl_dpy, m_config, EGL_NO_CONTEXT, &ctx_attribs[0]);
}
if (!egl_ctx)
{
INFO_LOG(VIDEO, "Error: eglCreateContext failed");
return false;
}
if (!egl_ctx)
{
INFO_LOG(VIDEO, "Error: eglCreateContext failed");
return false;
}
if (!CreateWindowSurface())
{
ERROR_LOG(VIDEO, "Error: CreateWindowSurface failed 0x%04x", eglGetError());
return false;
}
return true;
if (!CreateWindowSurface())
{
ERROR_LOG(VIDEO, "Error: CreateWindowSurface failed 0x%04x", eglGetError());
return false;
}
return true;
}
std::unique_ptr<cInterfaceBase> cInterfaceEGL::CreateSharedContext()
{
std::unique_ptr<cInterfaceBase> context = std::make_unique<cInterfaceEGL>();
if (!context->Create(this))
return nullptr;
return context;
std::unique_ptr<cInterfaceBase> context = std::make_unique<cInterfaceEGL>();
if (!context->Create(this))
return nullptr;
return context;
}
bool cInterfaceEGL::Create(cInterfaceBase* main_context)
{
cInterfaceEGL* egl_context = static_cast<cInterfaceEGL*>(main_context);
cInterfaceEGL* egl_context = static_cast<cInterfaceEGL*>(main_context);
egl_dpy = egl_context->egl_dpy;
m_core = egl_context->m_core;
m_config = egl_context->m_config;
m_supports_surfaceless = egl_context->m_supports_surfaceless;
m_is_shared = true;
m_has_handle = false;
egl_dpy = egl_context->egl_dpy;
m_core = egl_context->m_core;
m_config = egl_context->m_config;
m_supports_surfaceless = egl_context->m_supports_surfaceless;
m_is_shared = true;
m_has_handle = false;
EGLint ctx_attribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
EGLint ctx_attribs[] = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE};
switch (egl_context->GetMode())
{
case GLInterfaceMode::MODE_OPENGL:
ctx_attribs[0] = EGL_NONE;
break;
case GLInterfaceMode::MODE_OPENGLES2:
ctx_attribs[1] = 2;
break;
case GLInterfaceMode::MODE_OPENGLES3:
ctx_attribs[1] = 3;
break;
default:
INFO_LOG(VIDEO, "Unknown opengl mode set");
return false;
break;
}
switch (egl_context->GetMode())
{
case GLInterfaceMode::MODE_OPENGL:
ctx_attribs[0] = EGL_NONE;
break;
case GLInterfaceMode::MODE_OPENGLES2:
ctx_attribs[1] = 2;
break;
case GLInterfaceMode::MODE_OPENGLES3:
ctx_attribs[1] = 3;
break;
default:
INFO_LOG(VIDEO, "Unknown opengl mode set");
return false;
break;
}
if (egl_context->GetMode() == GLInterfaceMode::MODE_OPENGL)
eglBindAPI(EGL_OPENGL_API);
else
eglBindAPI(EGL_OPENGL_ES_API);
if (egl_context->GetMode() == GLInterfaceMode::MODE_OPENGL)
eglBindAPI(EGL_OPENGL_API);
else
eglBindAPI(EGL_OPENGL_ES_API);
egl_ctx = eglCreateContext(egl_dpy, m_config, egl_context->egl_ctx, ctx_attribs);
if (!egl_ctx)
{
INFO_LOG(VIDEO, "Error: eglCreateContext failed 0x%04x", eglGetError());
return false;
}
egl_ctx = eglCreateContext(egl_dpy, m_config, egl_context->egl_ctx, ctx_attribs);
if (!egl_ctx)
{
INFO_LOG(VIDEO, "Error: eglCreateContext failed 0x%04x", eglGetError());
return false;
}
if (!CreateWindowSurface())
{
ERROR_LOG(VIDEO, "Error: CreateWindowSurface failed 0x%04x", eglGetError());
return false;
}
return true;
if (!CreateWindowSurface())
{
ERROR_LOG(VIDEO, "Error: CreateWindowSurface failed 0x%04x", eglGetError());
return false;
}
return true;
}
bool cInterfaceEGL::CreateWindowSurface()
{
if (m_has_handle)
{
EGLNativeWindowType native_window = InitializePlatform(m_host_window, m_config);
egl_surf = eglCreateWindowSurface(egl_dpy, m_config, native_window, nullptr);
if (!egl_surf)
{
INFO_LOG(VIDEO, "Error: eglCreateWindowSurface failed");
return false;
}
}
else if (!m_supports_surfaceless)
{
EGLint attrib_list[] = {
EGL_NONE,
};
egl_surf = eglCreatePbufferSurface(egl_dpy, m_config, attrib_list);
if (!egl_surf)
{
INFO_LOG(VIDEO, "Error: eglCreatePbufferSurface failed");
return false;
}
}
else
{
egl_surf = EGL_NO_SURFACE;
}
return true;
if (m_has_handle)
{
EGLNativeWindowType native_window = InitializePlatform(m_host_window, m_config);
egl_surf = eglCreateWindowSurface(egl_dpy, m_config, native_window, nullptr);
if (!egl_surf)
{
INFO_LOG(VIDEO, "Error: eglCreateWindowSurface failed");
return false;
}
}
else if (!m_supports_surfaceless)
{
EGLint attrib_list[] = {
EGL_NONE,
};
egl_surf = eglCreatePbufferSurface(egl_dpy, m_config, attrib_list);
if (!egl_surf)
{
INFO_LOG(VIDEO, "Error: eglCreatePbufferSurface failed");
return false;
}
}
else
{
egl_surf = EGL_NO_SURFACE;
}
return true;
}
void cInterfaceEGL::DestroyWindowSurface()
{
if (egl_surf != EGL_NO_SURFACE && !eglDestroySurface(egl_dpy, egl_surf))
NOTICE_LOG(VIDEO, "Could not destroy window surface.");
egl_surf = EGL_NO_SURFACE;
if (egl_surf != EGL_NO_SURFACE && !eglDestroySurface(egl_dpy, egl_surf))
NOTICE_LOG(VIDEO, "Could not destroy window surface.");
egl_surf = EGL_NO_SURFACE;
}
bool cInterfaceEGL::MakeCurrent()
{
return eglMakeCurrent(egl_dpy, egl_surf, egl_surf, egl_ctx);
return eglMakeCurrent(egl_dpy, egl_surf, egl_surf, egl_ctx);
}
void cInterfaceEGL::UpdateHandle(void* window_handle)
{
m_host_window = (EGLNativeWindowType)window_handle;
m_has_handle = !!window_handle;
m_host_window = (EGLNativeWindowType)window_handle;
m_has_handle = !!window_handle;
}
void cInterfaceEGL::UpdateSurface()
{
ClearCurrent();
DestroyWindowSurface();
CreateWindowSurface();
MakeCurrent();
ClearCurrent();
DestroyWindowSurface();
CreateWindowSurface();
MakeCurrent();
}
bool cInterfaceEGL::ClearCurrent()
{
return eglMakeCurrent(egl_dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
return eglMakeCurrent(egl_dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
}
// Close backend
void cInterfaceEGL::Shutdown()
{
ShutdownPlatform();
if (egl_ctx)
{
if (!eglMakeCurrent(egl_dpy, egl_surf, egl_surf, egl_ctx))
NOTICE_LOG(VIDEO, "Could not release drawing context.");
eglMakeCurrent(egl_dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
if (!eglDestroyContext(egl_dpy, egl_ctx))
NOTICE_LOG(VIDEO, "Could not destroy drawing context.");
DestroyWindowSurface();
if (!m_is_shared && !eglTerminate(egl_dpy))
NOTICE_LOG(VIDEO, "Could not destroy display connection.");
egl_ctx = nullptr;
}
ShutdownPlatform();
if (egl_ctx)
{
if (!eglMakeCurrent(egl_dpy, egl_surf, egl_surf, egl_ctx))
NOTICE_LOG(VIDEO, "Could not release drawing context.");
eglMakeCurrent(egl_dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
if (!eglDestroyContext(egl_dpy, egl_ctx))
NOTICE_LOG(VIDEO, "Could not destroy drawing context.");
DestroyWindowSurface();
if (!m_is_shared && !eglTerminate(egl_dpy))
NOTICE_LOG(VIDEO, "Could not destroy display connection.");
egl_ctx = nullptr;
}
}

View File

@@ -0,0 +1,30 @@
// Copyright 2017 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#include "Common/GL/GLInterface/EGLHaiku.h"
#include <Window.h>
EGLDisplay cInterfaceEGLHaiku::OpenDisplay()
{
return eglGetDisplay(EGL_DEFAULT_DISPLAY);
}
EGLNativeWindowType cInterfaceEGLHaiku::InitializePlatform(EGLNativeWindowType host_window,
EGLConfig config)
{
EGLint format;
eglGetConfigAttrib(egl_dpy, config, EGL_NATIVE_VISUAL_ID, &format);
BWindow* window = reinterpret_cast<BWindow*>(host_window);
const int width = window->Size().width;
const int height = window->Size().height;
GLInterface->SetBackBufferDimensions(width, height);
return host_window;
}
void cInterfaceEGLHaiku::ShutdownPlatform()
{
}

View File

@@ -0,0 +1,16 @@
// Copyright 2017 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#pragma once
#include "Common/GL/GLInterface/EGL.h"
class cInterfaceEGLHaiku final : public cInterfaceEGL
{
protected:
EGLDisplay OpenDisplay() override;
EGLNativeWindowType InitializePlatform(EGLNativeWindowType host_window,
EGLConfig config) override;
void ShutdownPlatform() override;
};

View File

@@ -20,6 +20,8 @@
#include "Common/GL/GLInterface/EGL.h"
#elif ANDROID
#include "Common/GL/GLInterface/EGLAndroid.h"
#elif defined(__HAIKU__)
#include "Common/GL/GLInterface/BGL.h"
#else
#error Platform doesnt have a GLInterface
#endif
@@ -40,6 +42,8 @@ std::unique_ptr<cInterfaceBase> HostGL_CreateGLInterface()
#endif
#elif ANDROID
return std::make_unique<cInterfaceEGLAndroid>();
#elif defined(__HAIKU__)
return std::make_unique<cInterfaceBGL>();
#else
return nullptr;
#endif

View File

@@ -4,6 +4,7 @@
#pragma once
#include <windows.h>
#include <string>
#include "Common/GL/GLInterfaceBase.h"

View File

@@ -33,7 +33,7 @@ const std::string netplay_dolphin_ver = SCM_DESC_STR " Lin";
#endif
const std::string scm_rev_git_str = SCM_REV_STR;
const std::string scm_rev_cache_str = "201703210040";
const std::string scm_rev_cache_str = "201705092203";
const std::string scm_desc_str = SCM_DESC_STR;
const std::string scm_branch_str = SCM_BRANCH_STR;
const std::string scm_distributor_str = SCM_DISTRIBUTOR_STR;

View File

@@ -766,7 +766,7 @@ void SaveScreenShot()
SetState(CORE_PAUSE);
Renderer::SetScreenshot(GenerateScreenshotName());
g_renderer->SaveScreenshot(GenerateScreenshotName(), false);
if (!bPaused)
SetState(CORE_RUN);
@@ -780,7 +780,7 @@ void SaveScreenShot(const std::string& name)
std::string filePath = GenerateScreenshotFolderPath() + name + ".png";
Renderer::SetScreenshot(filePath);
g_renderer->SaveScreenshot(filePath, false);
if (!bPaused)
SetState(CORE_RUN);

View File

@@ -217,6 +217,11 @@ static wxString validation_layer_desc =
wxTRANSLATE("Enables validation of API calls made by the video backend, which may assist in "
"debugging graphical issues.\n\nIf unsure, leave this unchecked.");
static wxString vertex_rounding_desc =
wxTRANSLATE("Round 2D vertices to whole pixels. Fixes some "
"games at higher internal resolutions. This setting is disabled and turned off "
"at 1x IR.\n\nIf unsure, leave this unchecked.");
// Search for available resolutions - TODO: Move to Common?
static wxArrayString GetListOfResolutions()
{
@@ -853,7 +858,7 @@ VideoConfigDiag::VideoConfigDiag(wxWindow* parent, const std::string &title)
szr_hacks->Add(group_xfb, 0, wxEXPAND | wxALL, 5);
} // xfb
// Bounding Box
// Bounding Box
{
wxStaticBoxSizer* const group_bbox = new wxStaticBoxSizer(wxHORIZONTAL, page_hacks, _("Bounding Box"));
@@ -881,12 +886,17 @@ VideoConfigDiag::VideoConfigDiag(wxWindow* parent, const std::string &title)
// Disable while i fix opencl
//szr_other->Add(CreateCheckBox(page_hacks, _("OpenCL Texture Decoder"), (opencl_desc), vconfig.bEnableOpenCL));
szr_other->Add(CreateCheckBox(page_hacks, _("Fast Depth Calculation"), (fast_depth_calc_desc), vconfig.bFastDepthCalc));
vertex_rounding_checkbox =
CreateCheckBox(page_hacks, _("Vertex Rounding"), wxGetTranslation(vertex_rounding_desc),
vconfig.bVertexRounding);
szr_other->Add(vertex_rounding_checkbox);
szr_other->Add(Forced_LogicOp = CreateCheckBox(page_hacks, _("Force Logic Blending"), (forcedLogivOp_desc), vconfig.bForceLogicOpBlend));
//szr_other->Add(Predictive_FIFO = CreateCheckBox(page_hacks, _("Predictive FIFO"), (predictiveFifo_desc), vconfig.bPredictiveFifo));
//szr_other->Add(Wait_For_Shaders = CreateCheckBox(page_hacks, _("Wait for Shader Compilation"), (waitforshadercompilation_desc), vconfig.bWaitForShaderCompilation));
szr_other->Add(Async_Shader_compilation = CreateCheckBox(page_hacks, _("Full Async Shader Compilation"), (fullAsyncShaderCompilation_desc), vconfig.bFullAsyncShaderCompilation));
szr_other->Add(Compute_Shader_decoding = CreateCheckBox(page_hacks, _("Compute Texture Decoding"), (compute_texture_decoding_desc), vconfig.bEnableComputeTextureDecoding));
szr_other->Add(GPU_Texture_decoding = CreateCheckBox(page_hacks, _("GPU Texture Decoding"), (compute_texture_decoding_desc), vconfig.bEnableGPUTextureDecoding));
szr_other->Add(Compute_Shader_encoding = CreateCheckBox(page_hacks, _("Compute Texture Encoding"), (Compute_texture_encoding_desc), vconfig.bEnableComputeTextureEncoding));
wxStaticBoxSizer* const group_other = new wxStaticBoxSizer(wxVERTICAL, page_hacks, _("Other"));
group_other->Add(szr_other, 1, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, 5);
szr_hacks->Add(group_other, 0, wxEXPAND | wxALL, 5);
@@ -916,7 +926,7 @@ VideoConfigDiag::VideoConfigDiag(wxWindow* parent, const std::string &title)
wxGetTranslation(validation_layer_desc),
vconfig.bEnableValidationLayer));
}
wxStaticBoxSizer* const group_debug = new wxStaticBoxSizer(wxVERTICAL, page_advanced, _("Debugging"));
szr_advanced->Add(group_debug, 0, wxEXPAND | wxALL, 5);
@@ -1269,7 +1279,7 @@ void VideoConfigDiag::Event_PPShaderListRemove(wxCommandEvent& ev)
listbox_selected_ppshaders->Delete(sel);
if (!listbox_selected_ppshaders->IsEmpty())
{
if (sel > (int)listbox_selected_ppshaders->GetCount() - 1)
if (sel >(int)listbox_selected_ppshaders->GetCount() - 1)
listbox_selected_ppshaders->SetSelection(sel - 1);
else
listbox_selected_ppshaders->SetSelection(sel);
@@ -1477,8 +1487,8 @@ void VideoConfigDiag::OnUpdateUI(wxUpdateUIEvent& ev)
hires_texturemaps->Show(vconfig.backend_info.bSupportsNormalMaps);
Async_Shader_compilation->Show(vconfig.backend_info.APIType != API_OPENGL);
Compute_Shader_decoding->Show(vconfig.backend_info.bSupportsComputeTextureDecoding);
Async_Shader_compilation->Show(vconfig.backend_info.bSupportsAsyncShaderCompilation);
GPU_Texture_decoding->Show(vconfig.backend_info.bSupportsGPUTextureDecoding);
Compute_Shader_encoding->Show(vconfig.backend_info.bSupportsComputeTextureEncoding);
Forced_LogicOp->Show(vconfig.backend_info.APIType == API_D3D11);
@@ -1491,10 +1501,6 @@ void VideoConfigDiag::OnUpdateUI(wxUpdateUIEvent& ev)
// Things which shouldn't be changed during emulation
if (Core::IsRunning())
{
if (vconfig.backend_info.bSupportsComputeTextureDecoding)
{
Compute_Shader_decoding->Disable();
}
if (vconfig.backend_info.bSupportsComputeTextureEncoding)
{
Compute_Shader_encoding->Disable();
@@ -1533,6 +1539,15 @@ void VideoConfigDiag::OnUpdateUI(wxUpdateUIEvent& ev)
{
//Predictive_FIFO->Enable(!vconfig.bWaitForShaderCompilation);
}
// Don't enable 'vertex rounding' at native
if (vconfig.iEFBScale == SCALE_1X)
{
vertex_rounding_checkbox->Enable(false);
}
else
{
vertex_rounding_checkbox->Enable(true);
}
ev.Skip();
}

View File

@@ -159,11 +159,11 @@ protected:
wxStaticText* label_TextureScale;
SettingCheckBox* borderless_fullscreen;
SettingCheckBox* render_to_main_checkbox;
SettingCheckBox* Fast_efb_cache;
SettingCheckBox* emulate_efb_format_changes;
SettingCheckBox* Async_Shader_compilation;
SettingCheckBox* Compute_Shader_decoding;
SettingCheckBox* GPU_Texture_decoding;
SettingCheckBox* Compute_Shader_encoding;
SettingCheckBox* Forced_LogicOp;
SettingCheckBox* Predictive_FIFO;
@@ -178,6 +178,7 @@ protected:
wxButton* button_config_scalingshader;
wxCheckBox* progressive_scan_checkbox;
wxCheckBox* vertex_rounding_checkbox;
wxListBox* listbox_selected_ppshaders;
wxButton* button_move_ppshader_up;

View File

@@ -12,7 +12,7 @@
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{570215B7-E32F-4438-95AE-C8D955F9FCA3}</ProjectGuid>
<WindowsTargetPlatformVersion>10.0.14393.0</WindowsTargetPlatformVersion>
<WindowsTargetPlatformVersion>10.0.15063.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Label="Configuration">

View File

@@ -248,7 +248,7 @@ HRESULT Create(HWND wnd)
swap_chain_desc.SampleDesc.Quality = 0;
swap_chain_desc.Windowed = true;
swap_chain_desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;
swap_chain_desc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING;
swap_chain_desc.Flags = 0;
swap_chain_desc.BufferDesc.Width = s_xres;
swap_chain_desc.BufferDesc.Height = s_yres;
@@ -822,7 +822,7 @@ void Reset()
s_xres,
s_yres,
DXGI_FORMAT_R8G8B8A8_UNORM,
DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING));
0));
// recreate back buffer textures
@@ -897,7 +897,7 @@ void Present()
const double time_elapsed_since_last_present = static_cast<double>(current_qpc.QuadPart - s_last_present_qpc.QuadPart) / s_qpc_frequency.QuadPart;
unsigned int present_flags = g_ActiveConfig.IsVSync() ? 0 : DXGI_PRESENT_ALLOW_TEARING;
unsigned int present_flags = 0;
if (g_ActiveConfig.IsVSync() == false &&
time_elapsed_since_last_present < (1.0 / static_cast<double>(s_monitor_refresh_rate)) / 2.0

View File

@@ -6,6 +6,7 @@
#include <atomic>
#include <d3d12.h>
#include <dxgi.h>
#include <thread>
namespace DX12

View File

@@ -140,7 +140,7 @@ void StateCache::Init()
File::CreateDir(File::GetUserPath(D_SHADERCACHE_IDX));
std::string cache_filename = StringFromFormat("%sIdx12-%s-pso.cache", File::GetUserPath(D_SHADERCACHE_IDX).c_str(),
SConfig::GetInstance().m_strGameID.c_str());
SConfig::GetInstance().GetGameID().c_str());
PipelineStateCacheInserter inserter;
s_pso_disk_cache.OpenAndRead(cache_filename, inserter);

View File

@@ -95,7 +95,7 @@ void FramebufferManager::InitializeEFBCache(const D3D12_CLEAR_VALUE& color_clear
hr = D3D::device->CreateCommittedResource(&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT), D3D12_HEAP_FLAG_NONE, &tex_desc, D3D12_RESOURCE_STATE_COMMON, &depth_clear_value, IID_PPV_ARGS(buff.ReleaseAndGetAddressOf()));
CHECK(hr == S_OK, "create EFB depth cache texture (hr=%#x)", hr);
m_efb.depth_cache_tex = new D3DTexture2D(buff.Get(), TEXTURE_BIND_FLAG_RENDER_TARGET, depth_clear_value.Format, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, depth_clear_value.Format, false, D3D12_RESOURCE_STATE_COMMON);
D3D::SetDebugObjectName12(m_efb.depth_cache_tex->GetTex(), "EFB depth cache texture (used in Renderer::AccessEFB)");
D3D::SetDebugObjectName12(m_efb.depth_cache_tex->GetTex(), "EFB depth cache texture (used in g_renderer->AccessEFB)");
// AccessEFB - Sysmem buffer used to retrieve the pixel data from depth_read_texture
tex_desc = CD3DX12_RESOURCE_DESC::Buffer(EFB_CACHE_PITCH * EFB_HEIGHT);
@@ -105,10 +105,10 @@ void FramebufferManager::InitializeEFBCache(const D3D12_CLEAR_VALUE& color_clear
}
FramebufferManager::FramebufferManager()
FramebufferManager::FramebufferManager(u32 target_width, u32 target_height)
{
m_target_width = std::max(Renderer::GetTargetWidth(), 1);
m_target_height = std::max(Renderer::GetTargetHeight(), 1);
m_target_width = std::max(target_width, 16u);
m_target_height = std::max(target_height, 16u);
DXGI_SAMPLE_DESC sample_desc;
sample_desc.Count = g_ActiveConfig.iMultisamples;
@@ -314,8 +314,8 @@ void XFBSource::CopyEFB(float gamma)
D3D::DrawShadedTexQuad(
FramebufferManager::GetEFBDepthTexture(),
&rect,
Renderer::GetTargetWidth(),
Renderer::GetTargetHeight(),
g_renderer->GetTargetWidth(),
g_renderer->GetTargetHeight(),
StaticShaderCache::GetDepthCopyPixelShader(true),
StaticShaderCache::GetSimpleVertexShader(),
StaticShaderCache::GetSimpleVertexShaderInputLayout(),

View File

@@ -64,7 +64,7 @@ struct XFBSource final : public XFBSourceBase
class FramebufferManager final : public FramebufferManagerBase
{
public:
FramebufferManager();
FramebufferManager(u32 target_width, u32 target_height);
~FramebufferManager();
static D3DTexture2D*& GetEFBColorTexture();

View File

@@ -125,17 +125,17 @@ void PSTextureEncoder::Shutdown()
D3D::command_list_mgr->DestroyResourceAfterCurrentCommandListExecuted(m_out.Detach());
D3D::command_list_mgr->DestroyResourceAfterCurrentCommandListExecuted(m_out_readback_buffer.Detach());
D3D::command_list_mgr->DestroyResourceAfterCurrentCommandListExecuted(m_encode_params_buffer.Detach());
for (auto& it : m_static_shaders_blobs)
for (auto& it : m_shader_blobs)
{
SAFE_RELEASE(it);
}
m_static_shaders_blobs.clear();
m_static_shaders_map.clear();
m_shader_blobs.clear();
m_encoding_shaders.clear();
}
void PSTextureEncoder::Encode(u8* dst, u32 format, u32 native_width, u32 bytes_per_row, u32 num_blocks_y, u32 memory_stride,
bool is_depth_copy, const EFBRectangle& src_rect,
bool is_intensity, bool scale_by_half)
void PSTextureEncoder::Encode(u8* dst, const EFBCopyFormat& format, u32 native_width,
u32 bytes_per_row, u32 num_blocks_y, u32 memory_stride,
bool is_depth_copy, const EFBRectangle& src_rect, bool scale_by_half)
{
if (!m_ready) // Make sure we initialized OK
return;
@@ -187,9 +187,9 @@ void PSTextureEncoder::Encode(u8* dst, u32 format, u32 native_width, u32 bytes_p
D3D::DrawShadedTexQuad(efb_source,
target_rect.AsRECT(),
Renderer::GetTargetWidth(),
Renderer::GetTargetHeight(),
SetStaticShader(format, is_depth_copy, is_intensity, scale_by_half),
g_renderer->GetTargetWidth(),
g_renderer->GetTargetHeight(),
GetEncodingPixelShader(format),
StaticShaderCache::GetSimpleVertexShader(),
StaticShaderCache::GetSimpleVertexShaderInputLayout(),
D3D12_SHADER_BYTECODE(),
@@ -241,55 +241,31 @@ void PSTextureEncoder::Encode(u8* dst, u32 format, u32 native_width, u32 bytes_p
m_out_readback_buffer->Unmap(0, &write_range);
}
D3D12_SHADER_BYTECODE PSTextureEncoder::SetStaticShader(unsigned int dst_format, bool is_depth_copy,
bool is_intensity, bool scale_by_half)
D3D12_SHADER_BYTECODE PSTextureEncoder::GetEncodingPixelShader(const EFBCopyFormat& format)
{
ComboKey key = MakeComboKey(dst_format, is_depth_copy, is_intensity, scale_by_half);
auto iter = m_encoding_shaders.find(format);
if (iter != m_encoding_shaders.end())
return iter->second;
ComboMap::iterator it = m_static_shaders_map.find(key);
if (it == m_static_shaders_map.end())
D3DBlob* bytecode = nullptr;
const char* shader = TextureConversionShader::GenerateEncodingShader(format, API_TYPE::API_D3D11);
if (!D3D::CompilePixelShader(shader, &bytecode))
{
INFO_LOG(VIDEO, "Compiling efb encoding shader for dst_format 0x%X, is_depth_copy %d, is_intensity %d, scale_by_half %d",
dst_format, is_depth_copy, is_intensity ? 1 : 0, scale_by_half ? 1 : 0);
u32 format = dst_format;
if (is_depth_copy)
{
format |= _GX_TF_ZTF;
if (dst_format == 11)
format = GX_TF_Z16;
else if (format < GX_TF_Z8 || format > GX_TF_Z24X8)
format |= _GX_TF_CTF;
}
else
{
if (dst_format > GX_TF_RGBA8 || (dst_format < GX_TF_RGB565 && !is_intensity))
format |= _GX_TF_CTF;
}
D3DBlob* bytecode = nullptr;
const char* shader = TextureConversionShader::GenerateEncodingShader(format, API_D3D11);
if (!D3D::CompilePixelShader(shader, &bytecode))
{
WARN_LOG(VIDEO, "EFB encoder shader for dst_format 0x%X, is_depth_copy %d, is_intensity %d, scale_by_half %d failed to compile",
dst_format, is_depth_copy, is_intensity ? 1 : 0, scale_by_half ? 1 : 0);
m_static_shaders_blobs[key] = {};
return{};
}
D3D12_SHADER_BYTECODE new_shader = {
bytecode->Data(),
bytecode->Size()
};
it = m_static_shaders_map.insert(std::make_pair(key, new_shader)).first;
// Keep track of the D3DBlobs, so we can free them upon shutdown.
m_static_shaders_blobs.push_back(bytecode);
PanicAlert("Failed to compile texture encoding shader.");
m_encoding_shaders[format] = {};
return {};
}
return it->second;
D3D12_SHADER_BYTECODE new_shader = {
bytecode->Data(),
bytecode->Size()
};
m_encoding_shaders.emplace(format, new_shader);
// Keep track of the ID3DBlobs, so we can free them upon shutdown.
m_shader_blobs.push_back(bytecode);
return new_shader;
}
}

View File

@@ -7,6 +7,7 @@
#include "VideoBackends/D3D12/TextureEncoder.h"
#include "VideoCommon/TextureCacheBase.h"
#include "VideoCommon/TextureConversionShader.h"
namespace DX12
{
@@ -18,11 +19,12 @@ public:
void Init();
void Shutdown();
void Encode(u8* dst, u32 format, u32 native_width, u32 bytes_per_row, u32 num_blocks_y, u32 memory_stride,
bool is_depth_copy, const EFBRectangle& src_rect,
bool is_intensity, bool scale_by_half);
void Encode(u8* dst, const EFBCopyFormat& format, u32 native_width, u32 bytes_per_row,
u32 num_blocks_y, u32 memory_stride, bool is_depth_copy, const EFBRectangle& src_rect,
bool scale_by_half);
private:
D3D12_SHADER_BYTECODE GetEncodingPixelShader(const EFBCopyFormat& format);
bool m_ready = false;
ComPtr<ID3D12Resource> m_out;
@@ -33,20 +35,8 @@ private:
ComPtr<ID3D12Resource> m_encode_params_buffer;
void* m_encode_params_buffer_data = nullptr;
D3D12_SHADER_BYTECODE SetStaticShader(unsigned int dst_format,
bool is_depth_copy, bool is_intensity, bool scale_by_half);
using ComboKey = unsigned int; // Key for a shader combination
static ComboKey MakeComboKey(unsigned int dst_format,
bool is_depth_copy, bool is_intensity, bool scale_by_half)
{
return (dst_format << 4) | (is_depth_copy << 2) | (is_intensity ? (1 << 1) : 0)
| (scale_by_half ? (1 << 0) : 0);
}
using ComboMap = std::map<ComboKey, D3D12_SHADER_BYTECODE>;
ComboMap m_static_shaders_map;
std::vector<D3DBlob*> m_static_shaders_blobs;
std::map<EFBCopyFormat, D3D12_SHADER_BYTECODE> m_encoding_shaders;
std::vector<D3DBlob*> m_shader_blobs;
void InitializeRTV();

View File

@@ -95,10 +95,6 @@ D3DPostProcessingShader::~D3DPostProcessingShader()
{
for (RenderPassData& pass : m_passes)
{
for (InputBinding& input : pass.inputs)
{
ReleaseBindingSampler(input.texture_sampler);
}
ReleasePassNativeResources(pass);
}
D3DStreamBuffer* buffer = reinterpret_cast<D3DStreamBuffer*>(m_uniform_buffer);

View File

@@ -7,8 +7,10 @@
#include <memory>
#include <string>
#include <strsafe.h>
#include <tuple>
#include <unordered_map>
#include "Common/Align.h"
#include "Common/CommonTypes.h"
#include "Common/FileUtil.h"
@@ -46,10 +48,6 @@
namespace DX12
{
static u32 s_last_multisamples = 1;
static int s_last_stereo_mode = false;
static bool s_last_xfb_mode = false;
enum CLEAR_BLEND_DESC
{
CLEAR_BLEND_DESC_ALL_CHANNELS_ENABLED = 0,
@@ -98,15 +96,11 @@ static struct
} gx_state;
StateCache gx_state_cache;
static bool s_scissor_dirty = true;
static RECT s_scissor_rect{};
static bool s_viewport_dirty = true;
static D3D12_VIEWPORT s_vp;
static bool s_target_dirty = true;
static void SetupDeviceObjects()
void Renderer::SetupDeviceObjects()
{
g_framebuffer_manager = std::make_unique<FramebufferManager>();
g_framebuffer_manager = std::make_unique<FramebufferManager>(m_target_width, m_target_height);
D3D12_DEPTH_STENCIL_DESC depth_desc;
depth_desc.DepthEnable = FALSE;
@@ -160,14 +154,10 @@ static void SetupDeviceObjects()
D3D12_RASTERIZER_DESC rast_desc = CD3DX12_RASTERIZER_DESC(D3D12_FILL_MODE_SOLID, D3D12_CULL_MODE_NONE, false, 0, 0.f, 0.f, false, false, false, 0, D3D12_CONSERVATIVE_RASTERIZATION_MODE_OFF);
g_reset_rast_desc = rast_desc;
s_viewport_dirty = true;
s_target_dirty = true;
s_scissor_dirty = true;
}
// Kill off all device objects
static void TeardownDeviceObjects()
void Renderer::TeardownDeviceObjects()
{
g_framebuffer_manager.reset();
gx_state_cache.Clear();
@@ -202,27 +192,15 @@ Renderer::Renderer(void*& window_handle)
PanicAlert("3DVision not implemented on D3D12 backend.");
return;
}
m_backbuffer_width = D3D::GetBackBufferWidth();
m_backbuffer_height = D3D::GetBackBufferHeight();
s_backbuffer_width = D3D::GetBackBufferWidth();
s_backbuffer_height = D3D::GetBackBufferHeight();
FramebufferManagerBase::SetLastXfbWidth(MAX_XFB_WIDTH);
FramebufferManagerBase::SetLastXfbHeight(MAX_XFB_HEIGHT);
UpdateDrawRectangle();
s_last_multisamples = g_ActiveConfig.iMultisamples;
s_last_efb_scale = g_ActiveConfig.iEFBScale;
s_last_stereo_mode = g_ActiveConfig.iStereoMode;
s_last_xfb_mode = g_ActiveConfig.bUseRealXFB;
CalculateTargetSize();
PixelShaderManager::SetEfbScaleChanged();
SetupDeviceObjects();
m_post_processor = std::make_unique<D3DPostProcessor>();
if (!m_post_processor->Initialize())
PanicAlert("D3D: Failed to initialize post processor.");
m_last_multisamples = g_ActiveConfig.iMultisamples;
m_last_efb_scale = g_ActiveConfig.iEFBScale;
m_last_stereo_mode = g_ActiveConfig.iStereoMode;
m_last_xfb_mode = g_ActiveConfig.bUseRealXFB;
// Setup GX pipeline state
gx_state.blend.blend_enable = false;
@@ -244,6 +222,28 @@ Renderer::Renderer(void*& window_handle)
gx_state.raster.cull_mode = D3D12_CULL_MODE_NONE;
// Already transitioned to appropriate states a few lines up for the clears.
m_target_dirty = true;
D3D::BeginFrame();
}
void Renderer::Init()
{
FramebufferManagerBase::SetLastXfbWidth(MAX_XFB_WIDTH);
FramebufferManagerBase::SetLastXfbHeight(MAX_XFB_HEIGHT);
UpdateDrawRectangle();
CalculateTargetSize();
PixelShaderManager::SetEfbScaleChanged();
SetupDeviceObjects();
m_post_processor = std::make_unique<D3DPostProcessor>();
if (!m_post_processor->Initialize())
PanicAlert("D3D: Failed to initialize post processor.");
// Clear EFB textures
float clear_color[4] = { 0.f, 0.f, 0.f, 1.f };
FramebufferManager::GetEFBColorTexture()->TransitionToResourceState(D3D::current_command_list, D3D12_RESOURCE_STATE_RENDER_TARGET);
@@ -251,13 +251,8 @@ Renderer::Renderer(void*& window_handle)
D3D::current_command_list->ClearRenderTargetView(FramebufferManager::GetEFBColorTexture()->GetRTV(), clear_color, 0, nullptr);
D3D::current_command_list->ClearDepthStencilView(FramebufferManager::GetEFBDepthTexture()->GetDSV(), D3D12_CLEAR_FLAG_DEPTH, 0.f, 0, 0, nullptr);
s_vp = { 0.f, 0.f, static_cast<float>(s_target_width), static_cast<float>(s_target_height), D3D12_MIN_DEPTH, D3D12_MAX_DEPTH };
D3D::current_command_list->RSSetViewports(1, &s_vp);
// Already transitioned to appropriate states a few lines up for the clears.
s_target_dirty = true;
D3D::BeginFrame();
m_vp = { 0.f, 0.f, static_cast<float>(m_target_width), static_cast<float>(m_target_height), D3D12_MIN_DEPTH, D3D12_MAX_DEPTH };
D3D::current_command_list->RSSetViewports(1, &m_vp);
}
Renderer::~Renderer()
@@ -306,9 +301,14 @@ __declspec(noinline) bool Renderer::CheckForResize()
int client_width = rc_window.right - rc_window.left;
int client_height = rc_window.bottom - rc_window.top;
// Get the top-left corner of the client area in screen coordinates
POINT originPoint = { 0, 0 };
ClientToScreen(D3D::hWnd, &originPoint);
g_renderer->SetWindowRectangle(originPoint.x, originPoint.x + client_width, originPoint.y, originPoint.y + client_height);
// Sanity check
if ((client_width != Renderer::GetBackbufferWidth() ||
client_height != Renderer::GetBackbufferHeight()) &&
if ((client_width != g_renderer->GetBackbufferWidth() ||
client_height != g_renderer->GetBackbufferHeight()) &&
client_width >= 4 && client_height >= 4)
{
return true;
@@ -317,10 +317,10 @@ __declspec(noinline) bool Renderer::CheckForResize()
return false;
}
void Renderer::SetScissorRect(const TargetRectangle& rc)
void Renderer::SetScissorRect(const EFBRectangle& rc)
{
s_scissor_rect = *rc.AsRECT();
s_scissor_dirty = true;
m_scissor_rect = rc;
m_scissor_dirty = true;
}
void Renderer::SetColorMask()
@@ -413,7 +413,7 @@ u32 Renderer::AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data)
void Renderer::PokeEFB(EFBAccessType type, const EfbPokeData* points, size_t num_points)
{
if (s_target_dirty)
if (m_target_dirty)
{
FramebufferManager::RestoreEFBRenderTargets();
}
@@ -448,7 +448,7 @@ void Renderer::PokeEFB(EFBAccessType type, const EfbPokeData* points, size_t num
);
}
RestoreAPIState();
s_target_dirty = false;
m_target_dirty = false;
}
void Renderer::SetViewport()
@@ -503,9 +503,9 @@ void Renderer::SetViewport()
width = (x + width <= GetTargetWidth()) ? width : (GetTargetWidth() - x);
height = (y + height <= GetTargetHeight()) ? height : (GetTargetHeight() - y);
s_vp = { x, y, width, height, 1.0f - max_depth, 1.0f - min_depth };
m_vp = { x, y, width, height, 1.0f - max_depth, 1.0f - min_depth };
gx_state.zmode.reversed_depth = xfmem.viewport.zRange < 0;
s_viewport_dirty = true;
m_viewport_dirty = true;
}
void Renderer::ClearScreen(const EFBRectangle& rc, bool color_enable, bool alpha_enable, bool z_enable, u32 color, u32 z)
@@ -537,7 +537,7 @@ void Renderer::ClearScreen(const EFBRectangle& rc, bool color_enable, bool alpha
}
FramebufferManager::GetEFBColorTexture()->TransitionToResourceState(D3D::current_command_list, D3D12_RESOURCE_STATE_RENDER_TARGET);
if (s_target_dirty)
if (m_target_dirty)
{
FramebufferManager::RestoreEFBRenderTargets();
}
@@ -666,7 +666,7 @@ void Renderer::SetBlendMode(bool force_update)
// This function has the final picture. We adjust the aspect ratio here.
void Renderer::SwapImpl(u32 xfb_addr, u32 fb_width, u32 fb_stride, u32 fb_height, const EFBRectangle& rc, u64 ticks, float gamma)
{
if ( (!XFBWrited && !g_ActiveConfig.RealXFBEnabled()) || !fb_width || !fb_height)
if ( (!m_xfb_written && !g_ActiveConfig.RealXFBEnabled()) || !fb_width || !fb_height)
{
Core::Callback_VideoCopiedToXFB(false);
return;
@@ -695,7 +695,7 @@ void Renderer::SwapImpl(u32 xfb_addr, u32 fb_width, u32 fb_stride, u32 fb_height
float clear_color[4] = { 0.f, 0.f, 0.f, 1.f };
D3D::current_command_list->ClearRenderTargetView(D3D::GetBackBuffer()->GetRTV(), clear_color, 0, nullptr);
// Copy the framebuffer to screen.
const TargetSize dst_size = { s_target_width, s_target_height };
const TargetSize dst_size = { m_target_width, m_target_height };
DrawFrame(target_rc, rc, xfb_addr, xfb_source_list, xfb_count, D3D::GetBackBuffer(), dst_size, fb_width, fb_stride, fb_height, gamma);
// Dump frames
@@ -722,7 +722,7 @@ void Renderer::SwapImpl(u32 xfb_addr, u32 fb_width, u32 fb_stride, u32 fb_height
const bool window_resized = CheckForResize();
bool xfb_changed = s_last_xfb_mode != g_ActiveConfig.bUseRealXFB;
bool xfb_changed = m_last_xfb_mode != g_ActiveConfig.bUseRealXFB;
if (FramebufferManagerBase::LastXfbWidth() != fb_stride || FramebufferManagerBase::LastXfbHeight() != fb_height)
{
@@ -740,17 +740,17 @@ void Renderer::SwapImpl(u32 xfb_addr, u32 fb_width, u32 fb_stride, u32 fb_height
if (CalculateTargetSize() ||
xfb_changed ||
window_resized ||
s_last_efb_scale != g_ActiveConfig.iEFBScale ||
s_last_multisamples != g_ActiveConfig.iMultisamples ||
s_last_stereo_mode != g_ActiveConfig.iStereoMode)
m_last_efb_scale != g_ActiveConfig.iEFBScale ||
m_last_multisamples != g_ActiveConfig.iMultisamples ||
m_last_stereo_mode != g_ActiveConfig.iStereoMode)
{
s_last_xfb_mode = g_ActiveConfig.bUseRealXFB;
m_last_xfb_mode = g_ActiveConfig.bUseRealXFB;
// Block on any changes until the GPU catches up, so we can free resources safely.
D3D::command_list_mgr->ExecuteQueuedWork(true);
if (s_last_multisamples != g_ActiveConfig.iMultisamples)
if (m_last_multisamples != g_ActiveConfig.iMultisamples)
{
s_last_multisamples = g_ActiveConfig.iMultisamples;
m_last_multisamples = g_ActiveConfig.iMultisamples;
StaticShaderCache::InvalidateMSAAShaders();
}
@@ -758,13 +758,13 @@ void Renderer::SwapImpl(u32 xfb_addr, u32 fb_width, u32 fb_stride, u32 fb_height
{
// TODO: Aren't we still holding a reference to the back buffer right now?
D3D::Reset();
s_backbuffer_width = D3D::GetBackBufferWidth();
s_backbuffer_height = D3D::GetBackBufferHeight();
m_backbuffer_width = D3D::GetBackBufferWidth();
m_backbuffer_height = D3D::GetBackBufferHeight();
}
UpdateDrawRectangle();
s_last_efb_scale = g_ActiveConfig.iEFBScale;
m_last_efb_scale = g_ActiveConfig.iEFBScale;
PixelShaderManager::SetEfbScaleChanged();
@@ -772,7 +772,7 @@ void Renderer::SwapImpl(u32 xfb_addr, u32 fb_width, u32 fb_stride, u32 fb_height
D3D::current_command_list->OMSetRenderTargets(1, &D3D::GetBackBuffer()->GetRTV(), FALSE, nullptr);
g_framebuffer_manager.reset();
g_framebuffer_manager = std::make_unique<FramebufferManager>();
g_framebuffer_manager = std::make_unique<FramebufferManager>(m_target_width, m_target_height);
const float clear_color[4] = { 0.f, 0.f, 0.f, 1.f };
FramebufferManager::GetEFBColorTexture()->TransitionToResourceState(D3D::current_command_list, D3D12_RESOURCE_STATE_RENDER_TARGET);
@@ -780,9 +780,9 @@ void Renderer::SwapImpl(u32 xfb_addr, u32 fb_width, u32 fb_stride, u32 fb_height
FramebufferManager::GetEFBDepthTexture()->TransitionToResourceState(D3D::current_command_list, D3D12_RESOURCE_STATE_DEPTH_WRITE);
D3D::current_command_list->ClearDepthStencilView(FramebufferManager::GetEFBDepthTexture()->GetDSV(), D3D12_CLEAR_FLAG_DEPTH, 0.f, 0, 0, nullptr);
if (s_last_stereo_mode != g_ActiveConfig.iStereoMode)
if (m_last_stereo_mode != g_ActiveConfig.iStereoMode)
{
s_last_stereo_mode = g_ActiveConfig.iStereoMode;
m_last_stereo_mode = g_ActiveConfig.iStereoMode;
m_post_processor->SetReloadFlag();
}
}
@@ -820,7 +820,7 @@ void Renderer::DrawEFB(const TargetRectangle& t_rc, const EFBRectangle& source_r
TargetRectangle scaled_source_rc = Renderer::ConvertEFBRectangle(source_rc);
TargetRectangle target_rc = { t_rc.left, t_rc.top, t_rc.right, t_rc.bottom };
D3DTexture2D* tex = FramebufferManager::GetResolvedEFBColorTexture();
TargetSize tex_size(s_target_width, s_target_height);
TargetSize tex_size(m_target_width, m_target_height);
D3DTexture2D* blit_depth_tex = nullptr;
// Post processing active?
if (m_post_processor->ShouldTriggerOnSwap())
@@ -878,8 +878,8 @@ void Renderer::DrawVirtualXFB(const TargetRectangle& target_rc, u32 xfb_addr,
// The following code disables auto stretch. Kept for reference.
// scale draw area for a 1 to 1 pixel mapping with the draw target
//float vScale = static_cast<float>(fbHeight) / static_cast<float>(s_backbuffer_height);
//float hScale = static_cast<float>(fbWidth) / static_cast<float>(s_backbuffer_width);
//float vScale = static_cast<float>(fbHeight) / static_cast<float>(m_backbuffer_height);
//float hScale = static_cast<float>(fbWidth) / static_cast<float>(m_backbuffer_width);
//drawRc.top *= vScale;
//drawRc.bottom *= vScale;CalculateTargetSize
//drawRc.left *= hScale;
@@ -930,19 +930,16 @@ void Renderer::RestoreAPIState()
{
// Restores viewport/scissor rects, which might have been
// overwritten elsewhere (particularly the viewport).
s_viewport_dirty = true;
s_scissor_dirty = true;
s_target_dirty = true;
m_viewport_dirty = true;
m_scissor_dirty = true;
m_target_dirty = true;
}
static bool s_previous_use_dst_alpha = false;
static D3DVertexFormat* s_previous_vertex_format = nullptr;
void Renderer::ApplyState(bool use_dst_alpha)
{
if (use_dst_alpha != s_previous_use_dst_alpha)
if (use_dst_alpha != m_previous_use_dst_alpha)
{
s_previous_use_dst_alpha = use_dst_alpha;
m_previous_use_dst_alpha = use_dst_alpha;
D3D::command_list_mgr->SetCommandListDirtyState(COMMAND_LIST_STATE_PSO, true);
}
@@ -1000,24 +997,25 @@ void Renderer::ApplyState(bool use_dst_alpha)
{
RestoreAPIState();
}
if (s_viewport_dirty)
if (m_viewport_dirty)
{
D3D::current_command_list->RSSetViewports(1, &s_vp);
s_viewport_dirty = false;
D3D::current_command_list->RSSetViewports(1, &m_vp);
m_viewport_dirty = false;
}
if (s_scissor_dirty)
if (m_scissor_dirty)
{
D3D::current_command_list->RSSetScissorRects(1, &s_scissor_rect);
s_scissor_dirty = false;
D3D12_RECT src_s_rect = *ConvertEFBRectangle(m_scissor_rect).AsRECT();
D3D::current_command_list->RSSetScissorRects(1, &src_s_rect);
m_scissor_dirty = false;
}
if (s_target_dirty)
if (m_target_dirty)
{
FramebufferManager::RestoreEFBRenderTargets();
s_target_dirty = false;
m_target_dirty = false;
}
if (D3D::command_list_mgr->GetCommandListDirtyState(COMMAND_LIST_STATE_PSO) || s_previous_vertex_format != reinterpret_cast<D3DVertexFormat*>(VertexLoaderManager::GetCurrentVertexFormat()))
if (D3D::command_list_mgr->GetCommandListDirtyState(COMMAND_LIST_STATE_PSO) || m_previous_vertex_format != reinterpret_cast<D3DVertexFormat*>(VertexLoaderManager::GetCurrentVertexFormat()))
{
s_previous_vertex_format = reinterpret_cast<D3DVertexFormat*>(VertexLoaderManager::GetCurrentVertexFormat());
m_previous_vertex_format = reinterpret_cast<D3DVertexFormat*>(VertexLoaderManager::GetCurrentVertexFormat());
D3D12_PRIMITIVE_TOPOLOGY_TYPE topologyType = ShaderCache::GetCurrentPrimitiveTopology();
RasterizerState modifiableRastState = gx_state.raster;
@@ -1040,7 +1038,7 @@ void Renderer::ApplyState(bool use_dst_alpha)
HS,
PS,
VS,
s_previous_vertex_format, // D3D12_INPUT_LAYOUT_DESC InputLayout;
m_previous_vertex_format, // D3D12_INPUT_LAYOUT_DESC InputLayout;
gx_state.blend, // BlendState BlendState;
modifiableRastState, // RasterizerState RasterizerState;
gx_state.zmode, // ZMode DepthStencilState;
@@ -1235,11 +1233,6 @@ void Renderer::SetLogicOpMode()
D3D::command_list_mgr->SetCommandListDirtyState(COMMAND_LIST_STATE_PSO, true);
}
void Renderer::SetDitherMode()
{
// EXISTINGD3D11TODO: Set dither mode to bpmem.blendmode.dither
}
void Renderer::SetSamplerState(int stage, int tex_index, bool custom_tex)
{
const FourTexUnits& tex = bpmem.tex[tex_index];
@@ -1299,12 +1292,12 @@ u16 Renderer::BBoxRead(int index)
if (index < 2)
{
// left/right
value = value * EFB_WIDTH / s_target_width;
value = value * EFB_WIDTH / m_target_width;
}
else
{
// up/down
value = value * EFB_HEIGHT / s_target_height;
value = value * EFB_HEIGHT / m_target_height;
}
if (index & 1)
value++; // fix max values to describe the outer border
@@ -1319,11 +1312,11 @@ void Renderer::BBoxWrite(int index, u16 value)
local_value--;
if (index < 2)
{
local_value = local_value * s_target_width / EFB_WIDTH;
local_value = local_value * m_target_width / EFB_WIDTH;
}
else
{
local_value = local_value * s_target_height / EFB_HEIGHT;
local_value = local_value * m_target_height / EFB_HEIGHT;
}
BBox::Set(index, local_value);
@@ -1334,13 +1327,13 @@ void Renderer::BlitScreen(TargetRectangle dst_rect, TargetRectangle src_rect, Ta
{
if (g_ActiveConfig.iStereoMode == STEREO_SBS || g_ActiveConfig.iStereoMode == STEREO_TAB)
{
TargetRectangle leftRc, rightRc;
ConvertStereoRectangle(dst_rect, leftRc, rightRc);
TargetRectangle left_rc, right_rc;
std::tie(left_rc, right_rc) = ConvertStereoRectangle(dst_rect);
m_post_processor->BlitScreen(leftRc, dst_size, reinterpret_cast<uintptr_t>(dst_texture),
m_post_processor->BlitScreen(left_rc, dst_size, reinterpret_cast<uintptr_t>(dst_texture),
src_rect, src_size, reinterpret_cast<uintptr_t>(src_texture), reinterpret_cast<uintptr_t>(depth_texture), 0, Gamma);
m_post_processor->BlitScreen(rightRc, dst_size, reinterpret_cast<uintptr_t>(dst_texture),
m_post_processor->BlitScreen(right_rc, dst_size, reinterpret_cast<uintptr_t>(dst_texture),
src_rect, src_size, reinterpret_cast<uintptr_t>(src_texture), reinterpret_cast<uintptr_t>(depth_texture), 1, Gamma);
}
else if (g_ActiveConfig.iStereoMode == STEREO_3DVISION)
@@ -1451,7 +1444,7 @@ void Renderer::DumpFrame(const EFBRectangle& source_rc, u32 xfb_addr,
src = D3D::GetBackBuffer();
src_width = GetTargetRectangle().GetWidth();
src_height = GetTargetRectangle().GetHeight();
source_box = GetScreenshotSourceBox(target_rc, src_width, src_height);
source_box = GetScreenshotSourceBox(m_target_rectangle, src_width, src_height);
}
PrepareFrameDumpBuffer(src_width, src_height);

View File

@@ -18,14 +18,14 @@ class Renderer final : public ::Renderer
public:
Renderer(void *&window_handle);
~Renderer();
void Init() override;
void SetColorMask() override;
void SetBlendMode(bool force_Update) override;
void SetScissorRect(const TargetRectangle& rc) override;
void SetScissorRect(const EFBRectangle& rc) override;
void SetGenerationMode() override;
void SetDepthMode() override;
void SetLogicOpMode() override;
void SetDitherMode() override;
void SetSamplerState(int stage, int tex_index, bool custom_tex) override;
void SetInterlacingMode() override;
void SetViewport() override;
@@ -80,12 +80,24 @@ private:
void PrepareFrameDumpRenderTexture(u32 width, u32 height);
void PrepareFrameDumpBuffer(u32 width, u32 height);
void SetupDeviceObjects();
void TeardownDeviceObjects();
D3DTexture2D* m_frame_dump_render_texture = nullptr;
ID3D12Resource* m_frame_dump_buffer = nullptr;
u32 m_frame_dump_buffer_size = 0;
u32 m_frame_dump_render_texture_width = 0;
u32 m_frame_dump_render_texture_height = 0;
u32 m_last_multisamples = 1;
int m_last_stereo_mode = false;
bool m_last_xfb_mode = false;
bool m_scissor_dirty = true;
EFBRectangle m_scissor_rect{};
bool m_viewport_dirty = true;
D3D12_VIEWPORT m_vp;
bool m_target_dirty = true;
bool m_previous_use_dst_alpha = false;
D3DVertexFormat* m_previous_vertex_format = nullptr;
};
}

View File

@@ -29,7 +29,6 @@ namespace DX12
{
static std::unique_ptr<TextureEncoder> s_encoder;
static std::unique_ptr<TextureScaler> s_scaler;
static std::unique_ptr<D3DStreamBuffer> s_efb_copy_stream_buffer = nullptr;
static u32 s_efb_copy_last_cbuf_id = UINT_MAX;
@@ -213,50 +212,6 @@ void TextureCache::TCacheEntry::LoadMaterialMap(const u8* src, u32 width, u32 he
D3D::ReplaceTexture2D(m_nrm_texture->GetTex(), src, DXGI_format, width, height, width, level, m_nrm_texture->GetResourceUsageState());
}
void TextureCache::TCacheEntry::Load(const u8* src, u32 width, u32 height, u32 expandedWidth,
u32 expandedHeight, const s32 texformat, const u32 tlutaddr, const TlutFormat tlutfmt, u32 level)
{
u8* data = g_texture_cache->GetTemporalBuffer();
TexDecoder_Decode(
data,
src,
expandedWidth,
expandedHeight,
texformat,
tlutaddr,
tlutfmt,
DXGI_format == DXGI_FORMAT_R8G8B8A8_UNORM,
compressed);
if (is_scaled)
{
data = reinterpret_cast<u8*>(s_scaler->Scale(reinterpret_cast<u32*>(data), expandedWidth, height));
width *= g_ActiveConfig.iTexScalingFactor;
height *= g_ActiveConfig.iTexScalingFactor;
expandedWidth *= g_ActiveConfig.iTexScalingFactor;
}
D3D::ReplaceTexture2D(m_texture->GetTex(), data, DXGI_format, width, height, expandedWidth, level, m_texture->GetResourceUsageState());
}
void TextureCache::TCacheEntry::LoadFromTmem(const u8* ar_src, const u8* gb_src, u32 width, u32 height,
u32 expanded_width, u32 expanded_Height, u32 level)
{
u8* data = g_texture_cache->GetTemporalBuffer();
TexDecoder_DecodeRGBA8FromTmem(
reinterpret_cast<u32*>(data),
ar_src,
gb_src,
expanded_width,
expanded_Height);
if (is_scaled)
{
data = reinterpret_cast<u8*>(s_scaler->Scale(reinterpret_cast<u32*>(data), expanded_width, height));
width *= g_ActiveConfig.iTexScalingFactor;
height *= g_ActiveConfig.iTexScalingFactor;
expanded_width *= g_ActiveConfig.iTexScalingFactor;
}
D3D::ReplaceTexture2D(m_texture->GetTex(), data, DXGI_format, width, height, expanded_width, level, m_texture->GetResourceUsageState());
}
PC_TexFormat TextureCache::GetNativeTextureFormat(const s32 texformat, const TlutFormat tlutfmt, u32 width, u32 height)
{
const bool compressed_supported = ((width & 3) == 0) && ((height & 3) == 0);
@@ -413,8 +368,8 @@ void TextureCache::TCacheEntry::FromRenderTarget(bool is_depth_copy, const EFBRe
D3D::DrawShadedTexQuad(
efb_tex,
&sourcerect,
Renderer::GetTargetWidth(),
Renderer::GetTargetHeight(),
g_renderer->GetTargetWidth(),
g_renderer->GetTargetHeight(),
is_depth_copy ? StaticShaderCache::GetDepthMatrixPixelShader(multisampled)
: StaticShaderCache::GetColorMatrixPixelShader(multisampled),
StaticShaderCache::GetSimpleVertexShader(),
@@ -426,10 +381,9 @@ void TextureCache::TCacheEntry::FromRenderTarget(bool is_depth_copy, const EFBRe
g_renderer->RestoreAPIState();
}
void TextureCache::CopyEFB(u8* dst, u32 format, u32 native_width,
void TextureCache::CopyEFB(u8* dst, const EFBCopyFormat& format, u32 native_width,
u32 bytes_per_row, u32 num_blocks_y, u32 memory_stride,
bool is_depth_copy, const EFBRectangle& src_rect,
bool is_intensity, bool scale_by_half)
bool is_depth_copy, const EFBRectangle& src_rect, bool scale_by_half)
{
s_encoder->Encode(dst,
format,
@@ -439,7 +393,6 @@ void TextureCache::CopyEFB(u8* dst, u32 format, u32 native_width,
memory_stride,
is_depth_copy,
src_rect,
is_intensity,
scale_by_half);
}
@@ -668,7 +621,6 @@ TextureCache::TextureCache()
// FIXME: Is it safe here?
s_encoder = std::make_unique<PSTextureEncoder>();
s_encoder->Init();
s_scaler = std::make_unique<TextureScaler>();
s_texture_cache_entry_readback_buffer = nullptr;
s_texture_cache_entry_readback_buffer_size = 0;
@@ -713,7 +665,6 @@ TextureCache::~TextureCache()
{
s_encoder->Shutdown();
s_encoder.reset();
s_scaler.reset();
s_efb_copy_stream_buffer.reset();
m_palette_stream_buffer.reset();

View File

@@ -37,11 +37,6 @@ private:
void Load(const u8* src, u32 width, u32 height,
u32 expanded_width, u32 level) override;
void LoadMaterialMap(const u8* src, u32 width, u32 height, u32 level) override;
void Load(const u8* src, u32 width, u32 height, u32 expandedWidth,
u32 expandedHeight, const s32 texformat, const u32 tlutaddr, const TlutFormat tlutfmt, u32 level) override;
void LoadFromTmem(const u8* ar_src, const u8* gb_src, u32 width, u32 height,
u32 expanded_width, u32 expanded_Height, u32 level) override;
void FromRenderTarget(bool is_depth_copy, const EFBRectangle& src_rect,
bool scale_by_half, u32 cbuf_id, const float* colmat, u32 width, u32 height) override;
bool SupportsMaterialMap() const override
@@ -60,9 +55,9 @@ private:
TCacheEntryBase* CreateTexture(const TCacheEntryConfig& config) override;
bool Palettize(TCacheEntryBase* entry, const TCacheEntryBase* base_entry) override;
void CopyEFB(u8* dst, u32 format, u32 native_width, u32 bytes_per_row, u32 num_blocks_y, u32 memory_stride,
bool is_depth_copy, const EFBRectangle& src_rect,
bool is_intensity, bool scale_by_half) override;
void CopyEFB(u8* dst, const EFBCopyFormat& format, u32 native_width, u32 bytes_per_row,
u32 num_blocks_y, u32 memory_stride, bool is_depth_copy,
const EFBRectangle& src_rect, bool scale_by_half) override;
void LoadLut(u32 lutFmt, void* addr, u32 size) override;
bool CompileShaders() override
{

View File

@@ -25,9 +25,9 @@ public:
virtual void Init() = 0;
virtual void Shutdown() = 0;
// Returns size in bytes of encoded block of memory
virtual void Encode(u8* dst, u32 format, u32 native_width, u32 bytes_per_row, u32 num_blocks_y, u32 memory_stride,
bool is_depth_copy, const EFBRectangle& src_rect,
bool is_intensity, bool scale_by_half) = 0;
virtual void Encode(u8* dst, const EFBCopyFormat& format, u32 native_width, u32 bytes_per_row,
u32 num_blocks_y, u32 memory_stride, bool is_depth_copy, const EFBRectangle& src_rect,
bool scale_by_half) = 0;
};
}

View File

@@ -118,7 +118,7 @@ void VertexManager::Draw(u32 stride)
D3D_PRIMITIVE_TOPOLOGY d3d_primitive_topology = ShaderCache::GetActiveDomainShaderBytecode().pShaderBytecode != nullptr ? D3D_PRIMITIVE_TOPOLOGY_3_CONTROL_POINT_PATCHLIST : D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
switch (current_primitive_type)
switch (m_current_primitive_type)
{
case PRIMITIVE_POINTS:
d3d_primitive_topology = D3D_PRIMITIVE_TOPOLOGY_POINTLIST;
@@ -184,9 +184,9 @@ u16* VertexManager::GetIndexBuffer()
void VertexManager::ResetBuffer(u32 stride)
{
s_pCurBufferPointer = m_vertex_cpu_buffer.data();
s_pBaseBufferPointer = m_vertex_cpu_buffer.data();
s_pEndBufferPointer = s_pCurBufferPointer + MAXVBUFFERSIZE;
m_pCurBufferPointer = m_vertex_cpu_buffer.data();
m_pBaseBufferPointer = m_vertex_cpu_buffer.data();
m_pEndBufferPointer = m_pCurBufferPointer + MAXVBUFFERSIZE;
IndexGenerator::Start(reinterpret_cast<u16*>(m_index_cpu_buffer.data()));
}

View File

@@ -107,12 +107,12 @@ void VideoBackend::InitBackendInfo()
g_Config.backend_info.bSupportsGSInstancing = true;
g_Config.backend_info.bSupportsTessellation = true;
g_Config.backend_info.bSupportsSSAA = true;
g_Config.backend_info.bSupportsComputeTextureDecoding = false;
g_Config.backend_info.bSupportsGPUTextureDecoding = false;
g_Config.backend_info.bSupportsComputeTextureEncoding = false;
g_Config.backend_info.bSupportsDepthClamp = true;
g_Config.backend_info.bSupportsMultithreading = true;
g_Config.backend_info.bSupportsValidationLayer = true;
g_Config.backend_info.bSupportsReversedDepthRange = true;
g_Config.backend_info.bSupportsReversedDepthRange = false;
g_Config.backend_info.bSupportsInternalResolutionFrameDumps = true;
g_Config.backend_info.bSupportsAsyncShaderCompilation = true;
IDXGIFactory* factory;
@@ -165,9 +165,9 @@ bool VideoBackend::Initialize(void *window_handle)
{
if (window_handle == nullptr)
return false;
InitializeShared();
InitBackendInfo();
InitializeShared();
if (FAILED(D3D::Create((HWND)window_handle)))
return false;
@@ -179,6 +179,7 @@ void VideoBackend::Video_Prepare()
{
// internal interfaces
g_renderer = std::make_unique<Renderer>(m_window_handle);
g_renderer->Init();
g_texture_cache = std::make_unique<TextureCache>();
g_vertex_manager = std::make_unique<VertexManager>();
g_perf_query = std::make_unique<PerfQuery>();

View File

@@ -377,8 +377,7 @@ void CSTextureDecoder::Init()
CHECKANDEXIT(SUCCEEDED(hr), "create texture decoder lut srv");
D3D::SetDebugObjectName(m_lutSrv.get(), "texture decoder lut srv");
if (!(g_ActiveConfig.backend_info.bSupportsComputeTextureDecoding
&& g_ActiveConfig.bEnableComputeTextureDecoding))
if (!g_ActiveConfig.backend_info.bSupportsGPUTextureDecoding)
{
return;
}
@@ -439,7 +438,7 @@ const bool DecFuncSupported[] = {
false,//
false,//
false,//GX_TF_CMPR = 0xE,
true,//
false,//
};
bool CSTextureDecoder::FormatSupported(u32 srcFmt)
@@ -579,7 +578,7 @@ void CSTextureDecoder::LoadLut(u32 lutFmt, void* addr, u32 size)
D3D::context->UpdateSubresource(m_lutRsc.get(), 0, &box, addr, 0, 0);
m_lutFmt = lutFmt;
}
bool CSTextureDecoder::Decode(const u8* src, u32 srcsize, u32 srcFmt, u32 w, u32 h, u32 level, D3DTexture2D& dstTexture)
bool CSTextureDecoder::Decode(const u8* src, u32 srcsize, u32 srcFmt, u32 w, u32 h, u32 expandedw, u32 expandedh, u32 level, D3DTexture2D& dstTexture)
{
if (!m_ready || w < 32 || h < 32) // Make sure we initialized OK and texture size is big enough
return false;
@@ -624,7 +623,7 @@ bool CSTextureDecoder::Decode(const u8* src, u32 srcsize, u32 srcFmt, u32 w, u32
D3D::context->Unmap(m_params.get(), 0);
D3D::context->CSSetConstantBuffers(0, 1, D3D::ToAddr(m_params));
D3D::context->Dispatch((w + 7) / 8, (h + 7) / 8, 1);
D3D::context->Dispatch((expandedw + 7) / 8, (expandedh + 7) / 8, 1);
uav = nullptr;
D3D::context->CSSetUnorderedAccessViews(0, 1, &uav, nullptr);
@@ -640,75 +639,6 @@ bool CSTextureDecoder::Decode(const u8* src, u32 srcsize, u32 srcFmt, u32 w, u32
return true;
}
bool CSTextureDecoder::DecodeRGBAFromTMEM(u8 const * ar_src, u8 const * bg_src, u32 w, u32 h, D3DTexture2D& dstTexture)
{
if (!m_ready) // Make sure we initialized OK
return false;
if (!SetStaticShader(0xf, 0))
{
return false;
}
if (m_pool_idx == m_pool.size())
{
if (m_pool.size() < MAX_POOL_SIZE)
{
// create the pool texture here
auto desc = CD3D11_TEXTURE2D_DESC(DXGI_FORMAT_R8G8B8A8_UINT, 1024, 1024, 1, 1, D3D11_BIND_UNORDERED_ACCESS);
HRESULT hr;
PoolValue val;
hr = D3D::device->CreateTexture2D(&desc, nullptr, ToAddr(val.m_rsc));
CHECK(SUCCEEDED(hr), "create pool texture for texture decoder");
hr = D3D::device->CreateUnorderedAccessView(val.m_rsc.get(), nullptr, ToAddr(val.m_uav));
CHECK(SUCCEEDED(hr), "create pool UAV for texture decoder");
m_pool.push_back(std::move(val));
}
else
{
m_pool_idx = m_pool_idx % m_pool.size();
}
}
u32 aw = (w + 4)&~4;
u32 ah = (h + 4)&~4;
D3D11_BOX box{ 0, 0, 0, (aw*ah) << 1, 1, 1 };
D3D::context->UpdateSubresource(m_rawDataRsc.get(), 0, &box, ar_src, 0, 0);
D3D11_BOX box2{ (aw*ah) << 1, 0, 0, 2 * ((aw*ah) << 1), 1, 1 };
D3D::context->UpdateSubresource(m_rawDataRsc.get(), 0, &box2, bg_src, 0, 0);
ID3D11UnorderedAccessView* uav = m_pool[m_pool_idx].m_uav.get();
D3D::context->CSSetUnorderedAccessViews(0, 1, &uav, nullptr);
ID3D11ShaderResourceView* srvs[] = { m_rawDataSrv.get() };
D3D::context->CSSetShaderResources(0, 1, srvs);
D3D11_MAPPED_SUBRESOURCE map;
D3D::context->Map(m_params.get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &map);
((u32*)map.pData)[0] = w;
((u32*)map.pData)[1] = h;
D3D::context->Unmap(m_params.get(), 0);
D3D::context->CSSetConstantBuffers(0, 1, D3D::ToAddr(m_params));
D3D::context->Dispatch((w + 7) / 8, (h + 7) / 8, 1);
uav = nullptr;
D3D::context->CSSetUnorderedAccessViews(0, 1, &uav, nullptr);
D3D11_BOX pSrcBox;
pSrcBox.left = 0;
pSrcBox.top = 0;
pSrcBox.front = 0;
pSrcBox.right = w;
pSrcBox.bottom = h;
pSrcBox.back = 1;
D3D::context->CopySubresourceRegion(dstTexture.GetTex(), 0, 0, 0, 0, m_pool[m_pool_idx].m_rsc.get(), 0, &pSrcBox);
m_pool_idx++;
return true;
}
bool CSTextureDecoder::Depalettize(D3DTexture2D& dstTexture, D3DTexture2D& srcTexture, BaseType baseType, u32 width, u32 height)
{
ID3D11PixelShader* shader = GetDepalettizerPShader(baseType, m_lutFmt);

View File

@@ -23,8 +23,7 @@ public:
void Init() override;
void Shutdown() override;
bool FormatSupported(u32 srcFmt);
bool Decode(const u8* src, u32 srcsize, u32 srcFmt, u32 w, u32 h, u32 levels, D3DTexture2D& dstTexture) override;
bool DecodeRGBAFromTMEM(u8 const * ar_src, u8 const * bg_src, u32 width, u32 height, D3DTexture2D& dstTexture) override;
bool Decode(const u8* src, u32 srcsize, u32 srcFmt, u32 w, u32 h, u32 expandedw, u32 expandedh, u32 levels, D3DTexture2D& dstTexture) override;
bool Depalettize(D3DTexture2D& dstTexture, D3DTexture2D& srcTexture, BaseType baseType, u32 width, u32 height) override;
void LoadLut(u32 lutFmt, void* addr, u32 size) override;
private:

View File

@@ -25,11 +25,6 @@
// See <http://www.gamedev.net/topic/587232-dx11-dynamic-linking-compilation-warnings/>.
// Dynamic mode is disabled for now. To enable it, uncomment the line below.
//#define USE_DYNAMIC_MODE
// FIXME: When Microsoft fixes their HLSL compiler, make Dolphin enable dynamic
// mode on Shader Model 5-compatible cards.
namespace DX11
{
@@ -151,8 +146,12 @@ return lerp(float2(Params.TexLeft,Params.TexTop), float2(Params.TexRight,Params.
float4 Fetch_0(float2 coord)
{
float3 texCoord = float3(CalcTexCoord(coord), 0.0);
return EFBTexture.SampleLevel(EFBSampler, texCoord, 0);
float3 texCoord = float3(CalcTexCoord(coord), 0.0);
float4 color = EFBTexture.SampleLevel(EFBSampler, texCoord, 0);
#if DISCARD_ALPHA == 1
color.a = 1.0;
#endif
return color;
}
float4 Fetch_1(float2 coord)
@@ -167,32 +166,6 @@ uint4 bytes = uint4(
return bytes / 255.0;
}
#ifdef DYNAMIC_MODE
interface iFetch
{
float4 Fetch(float2 coord);
};
// Source format 0
class cFetch_0 : iFetch
{
float4 Fetch(float2 coord)
{ return Fetch_0(coord); }
};
// Source format 1
class cFetch_1 : iFetch
{
float4 Fetch(float2 coord)
{ return Fetch_1(coord); }
};
// Declare fetch interface; must be set by application
iFetch g_fetch;
#define IMP_FETCH g_fetch.Fetch
#endif // #ifdef DYNAMIC_MODE
#ifndef IMP_FETCH
#error No Fetch specified
#endif
@@ -213,32 +186,6 @@ sample = sample.rrrr;
return sample;
}
#ifdef DYNAMIC_MODE
interface iIntensity
{
float4 Intensity(float4 sample);
};
// Intensity off
class cIntensity_0 : iIntensity
{
float4 Intensity(float4 sample)
{ return Intensity_0(sample); }
};
// Intensity on
class cIntensity_1 : iIntensity
{
float4 Intensity(float4 sample)
{ return Intensity_1(sample); }
};
// Declare intensity interface; must be set by application
iIntensity g_intensity;
#define IMP_INTENSITY g_intensity.Intensity
#endif // #ifdef DYNAMIC_MODE
#ifndef IMP_INTENSITY
#error No Intensity specified
#endif
@@ -262,32 +209,6 @@ float4 sample3 = IMP_FETCH(ul+float2(1,1));
return 0.25 * (sample0+sample1+sample2+sample3);
}
#ifdef DYNAMIC_MODE
interface iScaledFetch
{
float4 ScaledFetch(float2 coord);
};
// Scale off
class cScaledFetch_0 : iScaledFetch
{
float4 ScaledFetch(float2 coord)
{ return ScaledFetch_0(coord); }
};
// Scale on
class cScaledFetch_1 : iScaledFetch
{
float4 ScaledFetch(float2 coord)
{ return ScaledFetch_1(coord); }
};
// Declare scaled fetch interface; must be set by application code
iScaledFetch g_scaledFetch;
#define IMP_SCALEDFETCH g_scaledFetch.ScaledFetch
#endif // #ifdef DYNAMIC_MODE
#ifndef IMP_SCALEDFETCH
#error No ScaledFetch specified
#endif
@@ -732,48 +653,6 @@ uint4 dw4 = UINT4_8888_BE(
return dw4;
}
#ifdef DYNAMIC_MODE
interface iGenerator
{
uint4 Generate(float2 cacheCoord);
};
class cGenerator_4 : iGenerator
{
uint4 Generate(float2 cacheCoord)
{ return Generate_4(cacheCoord); }
};
class cGenerator_5 : iGenerator
{
uint4 Generate(float2 cacheCoord)
{ return Generate_5(cacheCoord); }
};
class cGenerator_6 : iGenerator
{
uint4 Generate(float2 cacheCoord)
{ return Generate_6(cacheCoord); }
};
class cGenerator_8 : iGenerator
{
uint4 Generate(float2 cacheCoord)
{ return Generate_8(cacheCoord); }
};
class cGenerator_B : iGenerator
{
uint4 Generate(float2 cacheCoord)
{ return Generate_B(cacheCoord); }
};
// Declare generator interface; must be set by application
iGenerator g_generator;
#define IMP_GENERATOR g_generator.Generate
#endif
#ifndef IMP_GENERATOR
#error No generator specified
#endif
@@ -854,15 +733,6 @@ void CSTextureEncoder::Init()
CHECK(SUCCEEDED(hr), "create efb encode params buffer");
D3D::SetDebugObjectName(m_encodeParams.get(), "efb encoder params buffer");
// Create compute shader
#ifdef USE_DYNAMIC_MODE
if (!InitDynamicMode())
#else
if (!InitStaticMode())
#endif
return;
// Create efb texture sampler
D3D11_SAMPLER_DESC sd = CD3D11_SAMPLER_DESC(CD3D11_DEFAULT());
@@ -874,8 +744,7 @@ void CSTextureEncoder::Init()
m_ready = true;
// Warm up with shader cache
char cache_filename[MAX_PATH];
sprintf(cache_filename, "%sdx11-ENCODER-cs.cache", File::GetUserPath(D_SHADERCACHE_IDX).c_str());
std::string cache_filename = StringFromFormat("%sdx11-ENCODER-cs.cache", File::GetUserPath(D_SHADERCACHE_IDX).c_str());
m_shaderCache.OpenAndRead(cache_filename, ShaderCacheInserter(*this));
}
@@ -883,22 +752,6 @@ void CSTextureEncoder::Shutdown()
{
m_ready = false;
for (auto &e : m_fetchClass)
e.reset();
for (auto &e : m_scaledFetchClass)
e.reset();
for (auto &e : m_intensityClass)
e.reset();
for (auto &e : m_generatorClass)
e.reset();
m_linkageArray.clear();
m_classLinkage.reset();
m_dynamicShader.reset();
m_staticShaders.clear();
m_efbSampler.reset();
m_out.reset();
m_outUav.reset();
@@ -906,97 +759,95 @@ void CSTextureEncoder::Shutdown()
m_shaderCache.Close();
}
void CSTextureEncoder::Encode(u8* dest_ptr, u32 format, u32 native_width, u32 bytes_per_row, u32 num_blocks_y, u32 memory_stride,
bool is_depth_copy, bool bIsIntensityFmt, bool bScaleByHalf, const EFBRectangle& source)
void CSTextureEncoder::Encode(u8* dst, const EFBCopyFormat& format, u32 native_width,
u32 bytes_per_row, u32 num_blocks_y, u32 memory_stride,
bool is_depth_copy, const EFBRectangle& src_rect, bool scale_by_half)
{
if (!m_ready) // Make sure we initialized OK
return;
ComboKey key;
key.format = format;
key.scaled = scale_by_half;
auto shader = GetEncodingComputeShader(key);
if (shader == nullptr)
{
return;
}
HRESULT hr;
u32 cacheLinesPerRow = bytes_per_row / 32;
// Reset API
g_renderer->ResetAPIState();
// Set up all the state for EFB encoding
D3D::context->OMSetRenderTargets(0, nullptr, nullptr);
#ifdef USE_DYNAMIC_MODE
if (SetDynamicShader(format, is_depth_copy, bIsIntensityFmt, bScaleByHalf))
#else
if (SetStaticShader(format, is_depth_copy, bIsIntensityFmt, bScaleByHalf))
#endif
EFBRectangle fullSrcRect;
fullSrcRect.left = 0;
fullSrcRect.top = 0;
fullSrcRect.right = EFB_WIDTH;
fullSrcRect.bottom = EFB_HEIGHT;
TargetRectangle targetRect = g_renderer->ConvertEFBRectangle(fullSrcRect);
EFBEncodeParams params = { 0 };
params.NumHalfCacheLinesX = FLOAT(cacheLinesPerRow * 2);
params.NumBlocksY = FLOAT(num_blocks_y);
params.PosX = FLOAT(src_rect.left);
params.PosY = FLOAT(src_rect.top);
params.TexLeft = float(targetRect.left) / g_renderer->GetTargetWidth();
params.TexTop = float(targetRect.top) / g_renderer->GetTargetHeight();
params.TexRight = float(targetRect.right) / g_renderer->GetTargetWidth();
params.TexBottom = float(targetRect.bottom) / g_renderer->GetTargetHeight();
D3D::context->UpdateSubresource(m_encodeParams.get(), 0, nullptr, &params, 0, 0);
D3D::context->CSSetConstantBuffers(0, 1, D3D::ToAddr(m_encodeParams));
D3D::context->CSSetUnorderedAccessViews(0, 1, D3D::ToAddr(m_outUav), nullptr);
ID3D11ShaderResourceView* pEFB = is_depth_copy ?
FramebufferManager::GetResolvedEFBDepthTexture()->GetSRV() :
// FIXME: Instead of resolving EFB, it would be better to pick out a
// single sample from each pixel. The game may break if it isn't
// expecting the blurred edges around multisampled shapes.
FramebufferManager::GetResolvedEFBColorTexture()->GetSRV();
D3D::context->CSSetShader(shader, nullptr, 0);
D3D::context->CSSetShaderResources(0, 1, &pEFB);
D3D::context->CSSetSamplers(0, 1, D3D::ToAddr(m_efbSampler));
// Encode!
D3D::context->Dispatch((cacheLinesPerRow * 2 + 7) / 8, (num_blocks_y + 7) / 8, 1);
D3D11_BOX srcBox = CD3D11_BOX(0, 0, 0, (4 * 4)*cacheLinesPerRow * 2 * num_blocks_y, 1, 1);
D3D::context->CopySubresourceRegion(m_outStage.get(), 0, 0, 0, 0, m_out.get(), 0, &srcBox);
//
// Clean up state
IUnknown* nullDummy = nullptr;
D3D::context->CSSetUnorderedAccessViews(0, 1, (ID3D11UnorderedAccessView**)&nullDummy, nullptr);
D3D::context->CSSetShaderResources(0, 1, (ID3D11ShaderResourceView**)&nullDummy);
// Transfer staging buffer to GameCube/Wii RAM
// nVidia is unable to sync properly with a blocking Map
// That workaround works and NES games do not flick as hell anymore
D3D::context->Flush();
D3D11_MAPPED_SUBRESOURCE map = { 0 };
while ((hr = D3D::context->Map(m_outStage.get(), 0, D3D11_MAP_READ, D3D11_MAP_FLAG_DO_NOT_WAIT, &map)) != S_OK && hr == DXGI_ERROR_WAS_STILL_DRAWING)
{
D3D::context->OMSetRenderTargets(0, nullptr, nullptr);
Common::YieldCPU();
}
EFBRectangle fullSrcRect;
fullSrcRect.left = 0;
fullSrcRect.top = 0;
fullSrcRect.right = EFB_WIDTH;
fullSrcRect.bottom = EFB_HEIGHT;
TargetRectangle targetRect = g_renderer->ConvertEFBRectangle(fullSrcRect);
EFBEncodeParams params = { 0 };
params.NumHalfCacheLinesX = FLOAT(cacheLinesPerRow * 2);
params.NumBlocksY = FLOAT(num_blocks_y);
params.PosX = FLOAT(source.left);
params.PosY = FLOAT(source.top);
params.TexLeft = float(targetRect.left) / g_renderer->GetTargetWidth();
params.TexTop = float(targetRect.top) / g_renderer->GetTargetHeight();
params.TexRight = float(targetRect.right) / g_renderer->GetTargetWidth();
params.TexBottom = float(targetRect.bottom) / g_renderer->GetTargetHeight();
D3D::context->UpdateSubresource(m_encodeParams.get(), 0, nullptr, &params, 0, 0);
D3D::context->CSSetConstantBuffers(0, 1, D3D::ToAddr(m_encodeParams));
D3D::context->CSSetUnorderedAccessViews(0, 1, D3D::ToAddr(m_outUav), nullptr);
ID3D11ShaderResourceView* pEFB = is_depth_copy ?
FramebufferManager::GetResolvedEFBDepthTexture()->GetSRV() :
// FIXME: Instead of resolving EFB, it would be better to pick out a
// single sample from each pixel. The game may break if it isn't
// expecting the blurred edges around multisampled shapes.
FramebufferManager::GetResolvedEFBColorTexture()->GetSRV();
D3D::context->CSSetShaderResources(0, 1, &pEFB);
D3D::context->CSSetSamplers(0, 1, D3D::ToAddr(m_efbSampler));
// Encode!
D3D::context->Dispatch((cacheLinesPerRow * 2 + 7) / 8, (num_blocks_y + 7) / 8, 1);
D3D11_BOX srcBox = CD3D11_BOX(0, 0, 0, (4 * 4)*cacheLinesPerRow * 2 * num_blocks_y, 1, 1);
D3D::context->CopySubresourceRegion(m_outStage.get(), 0, 0, 0, 0, m_out.get(), 0, &srcBox);
//
// Clean up state
IUnknown* nullDummy = nullptr;
D3D::context->CSSetUnorderedAccessViews(0, 1, (ID3D11UnorderedAccessView**)&nullDummy, nullptr);
D3D::context->CSSetShaderResources(0, 1, (ID3D11ShaderResourceView**)&nullDummy);
// Transfer staging buffer to GameCube/Wii RAM
// nVidia is unable to sync properly with a blocking Map
// That workaround works and NES games do not flick as hell anymore
D3D::context->Flush();
D3D11_MAPPED_SUBRESOURCE map = { 0 };
while ((hr = D3D::context->Map(m_outStage.get(), 0, D3D11_MAP_READ, D3D11_MAP_FLAG_DO_NOT_WAIT, &map)) != S_OK && hr == DXGI_ERROR_WAS_STILL_DRAWING)
CHECK(SUCCEEDED(hr), "map staging buffer (0x%x)", hr);
if (hr == S_OK)
{
u8* src = (u8*)map.pData;
u32 readStride = std::min(bytes_per_row, map.RowPitch);
for (u32 y = 0; y < num_blocks_y; ++y)
{
Common::YieldCPU();
}
CHECK(SUCCEEDED(hr), "map staging buffer (0x%x)", hr);
if (hr == S_OK)
{
u8* src = (u8*)map.pData;
u32 readStride = std::min(bytes_per_row, map.RowPitch);
for (u32 y = 0; y < num_blocks_y; ++y)
{
memcpy(dest_ptr, src, readStride);
dest_ptr += memory_stride;
src += readStride;
}
D3D::context->Unmap(m_outStage.get(), 0);
memcpy(dst, src, readStride);
dst += memory_stride;
src += readStride;
}
D3D::context->Unmap(m_outStage.get(), 0);
}
// Restore API
@@ -1006,12 +857,6 @@ void CSTextureEncoder::Encode(u8* dest_ptr, u32 format, u32 native_width, u32 by
FramebufferManager::GetEFBDepthTexture()->GetDSV());
}
bool CSTextureEncoder::InitStaticMode()
{
// Nothing to really do.
return true;
}
static const char* FETCH_FUNC_NAMES[4] = {
"Fetch_0", "Fetch_1"
};
@@ -1024,244 +869,66 @@ static const char* INTENSITY_FUNC_NAMES[2] = {
"Intensity_0", "Intensity_1"
};
bool CSTextureEncoder::SetStaticShader(u32 dstFormat, bool is_depth_copy,
bool isIntensity, bool scaleByHalf)
ID3D11ComputeShader* CSTextureEncoder::GetEncodingComputeShader(const ComboKey& key)
{
size_t scaledFetchNum = scaleByHalf ? 1 : 0;
size_t intensityNum = isIntensity ? 1 : 0;
size_t generatorNum = dstFormat & 0xF;
size_t generatorNum = static_cast<size_t>(key.format.copy_format) & 0xF;
auto iter = m_encoding_shaders.find(key);
if (iter != m_encoding_shaders.end())
return iter->second.get();
ComboKey key = MakeComboKey(dstFormat, is_depth_copy, isIntensity, scaleByHalf, DX11::D3D::GetFeatureLevel() >= D3D_FEATURE_LEVEL_11_0);
ComboMap::iterator it = m_staticShaders.find(key);
ID3D11ComputeShader* shader{};
if (it != m_staticShaders.end())
const char* generatorFuncName = nullptr;
switch (generatorNum)
{
shader = it->second.get();
}
else
{
const char* generatorFuncName = nullptr;
switch (generatorNum)
{
case 0x0: generatorFuncName = "Generate_0"; break;
case 0x1: generatorFuncName = "Generate_1"; break;
case 0x2: generatorFuncName = "Generate_2"; break;
case 0x3: generatorFuncName = "Generate_3"; break;
case 0x4: generatorFuncName = "Generate_4"; break;
case 0x5: generatorFuncName = "Generate_5"; break;
case 0x6: generatorFuncName = "Generate_6"; break;
case 0x7: generatorFuncName = "Generate_7"; break;
case 0x8: generatorFuncName = "Generate_8"; break;
case 0x9: generatorFuncName = "Generate_9"; break;
case 0xA: generatorFuncName = "Generate_A"; break;
case 0xB: generatorFuncName = "Generate_B"; break;
case 0xC: generatorFuncName = "Generate_C"; break;
default:
WARN_LOG(VIDEO, "No generator available for dst format 0x%X; aborting", generatorNum);
m_staticShaders[key] = nullptr;
return false;
}
INFO_LOG(VIDEO, "Compiling efb encoding shader for dstFormat 0x%X, is_depth_copy %d, isIntensity %d, scaleByHalf %d",
dstFormat, is_depth_copy, isIntensity ? 1 : 0, scaleByHalf ? 1 : 0);
// Shader permutation not found, so compile it
D3DBlob bytecode;
D3D_SHADER_MACRO macros[] = {
{ "IMP_FETCH", FETCH_FUNC_NAMES[is_depth_copy] },
{ "IMP_SCALEDFETCH", SCALEDFETCH_FUNC_NAMES[scaledFetchNum] },
{ "IMP_INTENSITY", INTENSITY_FUNC_NAMES[intensityNum] },
{ "IMP_GENERATOR", generatorFuncName },
{ "SHADER_MODEL", DX11::D3D::GetFeatureLevel() >= D3D_FEATURE_LEVEL_11_0 ? "5" : "4" },
{ nullptr, nullptr }
};
if (!D3D::CompileShader(D3D::ShaderType::Compute, EFB_ENCODE_CS, bytecode, macros))
{
WARN_LOG(VIDEO, "EFB encoder shader for dstFormat 0x%X, is_depth_copy %d, isIntensity %d, scaleByHalf %d failed to compile",
dstFormat, is_depth_copy, isIntensity ? 1 : 0, scaleByHalf ? 1 : 0);
// Add dummy shader to map to prevent trying to compile over and
// over again
m_staticShaders[key] = nullptr;
return false;
}
m_shaderCache.Append(key, bytecode.Data(), (u32)bytecode.Size());
shader = InsertShader(key, bytecode.Data(), (u32)bytecode.Size());
case 0x0: generatorFuncName = "Generate_0"; break;
case 0x1: generatorFuncName = "Generate_1"; break;
case 0x2: generatorFuncName = "Generate_2"; break;
case 0x3: generatorFuncName = "Generate_3"; break;
case 0x4: generatorFuncName = "Generate_4"; break;
case 0x5: generatorFuncName = "Generate_5"; break;
case 0x6: generatorFuncName = "Generate_6"; break;
case 0x7: generatorFuncName = "Generate_7"; break;
case 0x8: generatorFuncName = "Generate_8"; break;
case 0x9: generatorFuncName = "Generate_9"; break;
case 0xA: generatorFuncName = "Generate_A"; break;
case 0xB: generatorFuncName = "Generate_B"; break;
case 0xC: generatorFuncName = "Generate_C"; break;
default:
WARN_LOG(VIDEO, "No generator available for dst format 0x%X; aborting", generatorNum);
m_encoding_shaders[key] = nullptr;
return false;
}
if (shader)
// Shader permutation not found, so compile it
D3DBlob bytecode;
D3D_SHADER_MACRO macros[] = {
{ "IMP_FETCH", FETCH_FUNC_NAMES[(key.format.copy_format & _GX_TF_ZTF) != 0 ? 1 : 0] },
{ "IMP_SCALEDFETCH", SCALEDFETCH_FUNC_NAMES[key.scaled] },
{ "IMP_INTENSITY", INTENSITY_FUNC_NAMES[key.format.copy_format < GX_TF_RGB565] },
{ "IMP_GENERATOR", generatorFuncName },
{ "SHADER_MODEL", DX11::D3D::GetFeatureLevel() >= D3D_FEATURE_LEVEL_11_0 ? "5" : "4" },
{ "DISCARD_ALPHA", key.format.efb_format == PEControl::RGBA6_Z24 ? "0" : "1" },
{ nullptr, nullptr }
};
if (!D3D::CompileShader(D3D::ShaderType::Compute, EFB_ENCODE_CS, bytecode, macros))
{
D3D::context->CSSetShader(shader, nullptr, 0);
return true;
WARN_LOG(VIDEO, "EFB encoder shader for dstFormat 0x%X, srcformat 0x%X, scaled : %d failed to compile",
key.format.copy_format, key.format.efb_format, key.scaled ? 1 : 0);
// Add dummy shader to map to prevent trying to compile over and
// over again
m_encoding_shaders[key] = nullptr;
return false;
}
return false;
m_shaderCache.Append(key, bytecode.Data(), (u32)bytecode.Size());
return InsertShader(key, bytecode.Data(), (u32)bytecode.Size());
}
ID3D11ComputeShader* CSTextureEncoder::InsertShader(ComboKey const &key, u8 const *data, u32 sz)
ID3D11ComputeShader* CSTextureEncoder::InsertShader(const ComboKey &key, u8 const *data, u32 sz)
{
ID3D11ComputeShader* newShader;
HRESULT hr = D3D::device->CreateComputeShader(data, sz, nullptr, &newShader);
CHECK(SUCCEEDED(hr), "create efb encoder pixel shader");
m_staticShaders.emplace(key, D3D::UniquePtr<ID3D11ComputeShader>(newShader));
m_encoding_shaders.emplace(key, D3D::UniquePtr<ID3D11ComputeShader>(newShader));
return newShader;
}
bool CSTextureEncoder::InitDynamicMode()
{
HRESULT hr;
D3D_SHADER_MACRO macros[] = {
{ "DYNAMIC_MODE", nullptr },
{ nullptr, nullptr }
};
D3DBlob bytecode;
if (!D3D::CompileShader(D3D::ShaderType::Compute, EFB_ENCODE_CS, bytecode, macros))
{
ERROR_LOG(VIDEO, "EFB encode pixel shader failed to compile");
return false;
}
hr = D3D::device->CreateClassLinkage(ToAddr(m_classLinkage));
CHECK(SUCCEEDED(hr), "create efb encode class linkage");
D3D::SetDebugObjectName(m_classLinkage.get(), "efb encoder class linkage");
hr = D3D::device->CreateComputeShader(bytecode.Data(), bytecode.Size(), m_classLinkage.get(), ToAddr(m_dynamicShader));
CHECK(SUCCEEDED(hr), "create efb encode pixel shader");
D3D::SetDebugObjectName(m_dynamicShader.get(), "efb encoder pixel shader");
// Use D3DReflect
D3D::UniquePtr<ID3D11ShaderReflection> reflect;
hr = HLSLCompiler::getInstance().Reflect(bytecode.Data(), bytecode.Size(), IID_ID3D11ShaderReflection, ToAddr(reflect));
CHECK(SUCCEEDED(hr), "reflect on efb encoder shader");
// Get number of slots and create dynamic linkage array
UINT numSlots = reflect->GetNumInterfaceSlots();
m_linkageArray.resize(numSlots);
// Get interface slots
ID3D11ShaderReflectionVariable* var = reflect->GetVariableByName("g_fetch");
m_fetchSlot = var->GetInterfaceSlot(0);
var = reflect->GetVariableByName("g_scaledFetch");
m_scaledFetchSlot = var->GetInterfaceSlot(0);
var = reflect->GetVariableByName("g_intensity");
m_intensitySlot = var->GetInterfaceSlot(0);
var = reflect->GetVariableByName("g_generator");
m_generatorSlot = var->GetInterfaceSlot(0);
INFO_LOG(VIDEO, "Fetch slot %d, scaledFetch slot %d, intensity slot %d, generator slot %d",
m_fetchSlot, m_scaledFetchSlot, m_intensitySlot, m_generatorSlot);
// Class instances will be created at the time they are used
for (auto &e : m_fetchClass)
e.reset();
for (auto &e : m_scaledFetchClass)
e.reset();
for (auto &e : m_intensityClass)
e.reset();
for (auto &e : m_generatorClass)
e.reset();
return true;
}
static const char* FETCH_CLASS_NAMES[2] = {
"cFetch_0", "cFetch_1"
};
static const char* SCALEDFETCH_CLASS_NAMES[2] = {
"cScaledFetch_0", "cScaledFetch_1"
};
static const char* INTENSITY_CLASS_NAMES[2] = {
"cIntensity_0", "cIntensity_1"
};
bool CSTextureEncoder::SetDynamicShader(u32 dstFormat,
bool is_depth_copy, bool isIntensity, bool scaleByHalf)
{
size_t scaledFetchNum = scaleByHalf ? 1 : 0;
size_t intensityNum = isIntensity ? 1 : 0;
size_t generatorNum = dstFormat & 0xF;
// FIXME: Not all the possible generators are available as classes yet.
// When dynamic mode is usable, implement them.
const char* generatorName = nullptr;
switch (generatorNum)
{
case 0x4: generatorName = "cGenerator_4"; break;
case 0x5: generatorName = "cGenerator_5"; break;
case 0x6: generatorName = "cGenerator_6"; break;
case 0x8: generatorName = "cGenerator_8"; break;
case 0xB: generatorName = "cGenerator_B"; break;
default:
WARN_LOG(VIDEO, "No generator available for dst format 0x%X; aborting", generatorNum);
return false;
}
// Make sure class instances are available
if (!m_fetchClass[is_depth_copy])
{
INFO_LOG(VIDEO, "Creating %s class instance for encoder 0x%X",
FETCH_CLASS_NAMES[is_depth_copy], dstFormat);
HRESULT hr = m_classLinkage->CreateClassInstance(
FETCH_CLASS_NAMES[is_depth_copy], 0, 0, 0, 0, ToAddr(m_fetchClass[is_depth_copy]));
CHECK(SUCCEEDED(hr), "create fetch class instance");
}
if (!m_scaledFetchClass[scaledFetchNum])
{
INFO_LOG(VIDEO, "Creating %s class instance for encoder 0x%X",
SCALEDFETCH_CLASS_NAMES[scaledFetchNum], dstFormat);
HRESULT hr = m_classLinkage->CreateClassInstance(
SCALEDFETCH_CLASS_NAMES[scaledFetchNum], 0, 0, 0, 0,
ToAddr(m_scaledFetchClass[scaledFetchNum]));
CHECK(SUCCEEDED(hr), "create scaled fetch class instance");
}
if (!m_intensityClass[intensityNum])
{
INFO_LOG(VIDEO, "Creating %s class instance for encoder 0x%X",
INTENSITY_CLASS_NAMES[intensityNum], dstFormat);
HRESULT hr = m_classLinkage->CreateClassInstance(
INTENSITY_CLASS_NAMES[intensityNum], 0, 0, 0, 0,
ToAddr(m_intensityClass[intensityNum]));
CHECK(SUCCEEDED(hr), "create intensity class instance");
}
if (!m_generatorClass[generatorNum])
{
INFO_LOG(VIDEO, "Creating %s class instance for encoder 0x%X",
generatorName, dstFormat);
HRESULT hr = m_classLinkage->CreateClassInstance(
generatorName, 0, 0, 0, 0, ToAddr(m_generatorClass[generatorNum]));
CHECK(SUCCEEDED(hr), "create generator class instance");
}
// Assemble dynamic linkage array
if (m_fetchSlot != UINT(-1))
m_linkageArray[m_fetchSlot] = m_fetchClass[is_depth_copy].get();
if (m_scaledFetchSlot != UINT(-1))
m_linkageArray[m_scaledFetchSlot] = m_scaledFetchClass[scaledFetchNum].get();
if (m_intensitySlot != UINT(-1))
m_linkageArray[m_intensitySlot] = m_intensityClass[intensityNum].get();
if (m_generatorSlot != UINT(-1))
m_linkageArray[m_generatorSlot] = m_generatorClass[generatorNum].get();
D3D::context->CSSetShader(m_dynamicShader.get(),
m_linkageArray.empty() ? nullptr : m_linkageArray.data(),
(UINT)m_linkageArray.size());
return true;
}
}

View File

@@ -4,6 +4,8 @@
#pragma once
#include <tuple>
#include "Common/LinearDiskCache.h"
#include "VideoBackends/DX11/D3DPtr.h"
#include "VideoBackends/DX11/TextureEncoder.h"
@@ -20,10 +22,25 @@ public:
void Init();
void Shutdown();
void Encode(u8* dest_ptr, u32 format, u32 native_width, u32 bytes_per_row, u32 num_blocks_y, u32 memory_stride,
bool is_depth_copy, bool bIsIntensityFmt, bool bScaleByHalf, const EFBRectangle& source) override;
void Encode(u8* dst, const EFBCopyFormat& format, u32 native_width, u32 bytes_per_row,
u32 num_blocks_y, u32 memory_stride, bool is_depth_copy, const EFBRectangle& src_rect,
bool scale_by_half);
private:
struct ComboKey{
EFBCopyFormat format;
bool scaled;
bool operator<(const ComboKey& rhs) const
{
return std::tie(format, scaled) < std::tie(rhs.format, rhs.scaled);
}
bool operator == (const ComboKey& rhs) const
{
return format == rhs.format && scaled == rhs.scaled;
}
};
ID3D11ComputeShader* GetEncodingComputeShader(const ComboKey& key);
ID3D11ComputeShader* InsertShader(const ComboKey& key, u8 const *data, u32 sz);
bool m_ready{};
D3D::BufferPtr m_out;
@@ -33,31 +50,14 @@ private:
D3D::BufferPtr m_encodeParams;
D3D::SamplerStatePtr m_efbSampler;
// Stuff only used in static-linking mode (SM4.0-compatible)
bool InitStaticMode();
bool SetStaticShader(u32 dstFormat,
bool is_depth_copy, bool isIntensity, bool scaleByHalf);
typedef u32 ComboKey; // Key for a shader combination
ID3D11ComputeShader* InsertShader(ComboKey const &key, u8 const *data, u32 sz);
ComboKey MakeComboKey(u32 dstFormat,
bool is_depth_copy, bool isIntensity, bool scaleByHalf, bool model5)
{
return (model5 ? (1 << 24) : 0) | (dstFormat << 4) | (is_depth_copy << 2) | (isIntensity ? (1 << 1) : 0)
| (scaleByHalf ? (1 << 0) : 0);
}
typedef std::map<ComboKey, D3D::ComputeShaderPtr> ComboMap;
ComboMap m_staticShaders;
std::map<ComboKey, D3D::ComputeShaderPtr> m_encoding_shaders;
class ShaderCacheInserter : public LinearDiskCacheReader<ComboKey, u8>
{
public:
void Read(const ComboKey &key, const u8 *value, u32 value_size)
void Read(const ComboKey& key, const u8 *value, u32 value_size)
{
encoder_.InsertShader(key, value, value_size);
}
@@ -70,34 +70,6 @@ private:
LinearDiskCache<ComboKey, u8> m_shaderCache;
// Stuff only used for dynamic-linking mode (SM5.0+, available as soon as
// Microsoft fixes their bloody HLSL compiler)
bool InitDynamicMode();
bool SetDynamicShader(u32 dstFormat,
bool is_depth_copy, bool isIntensity, bool scaleByHalf);
D3D::ComputeShaderPtr m_dynamicShader;
D3D::ClkPtr m_classLinkage;
// Interface slots
UINT m_fetchSlot;
UINT m_scaledFetchSlot;
UINT m_intensitySlot;
UINT m_generatorSlot;
// Class instances
// Fetch: 0 is RGB, 1 is Z
D3D::CiPtr m_fetchClass[2];
// ScaledFetch: 0 is off, 1 is on
D3D::CiPtr m_scaledFetchClass[2];
// Intensity: 0 is off, 1 is on
D3D::CiPtr m_intensityClass[2];
// Generator: one for each dst format, 16 total
D3D::CiPtr m_generatorClass[16];
std::vector<ID3D11ClassInstance*> m_linkageArray;
};
}

View File

@@ -86,14 +86,14 @@ void FramebufferManager::InitializeEFBCache()
CHECK(hr == S_OK, "create EFB color cache texture (hr=%#x)", hr);
m_efb.color_cache_tex = new D3DTexture2D(buf, D3D11_BIND_RENDER_TARGET);
SAFE_RELEASE(buf);
D3D::SetDebugObjectName((ID3D11DeviceChild*)m_efb.color_cache_tex->GetTex(), "EFB color read texture (used in Renderer::AccessEFB)");
D3D::SetDebugObjectName((ID3D11DeviceChild*)m_efb.color_cache_tex->GetRTV(), "EFB color read texture render target view (used in Renderer::AccessEFB)");
D3D::SetDebugObjectName((ID3D11DeviceChild*)m_efb.color_cache_tex->GetTex(), "EFB color read texture (used in g_renderer->AccessEFB)");
D3D::SetDebugObjectName((ID3D11DeviceChild*)m_efb.color_cache_tex->GetRTV(), "EFB color read texture render target view (used in g_renderer->AccessEFB)");
// AccessEFB - Sysmem buffer used to retrieve the pixel data from color_tex
tex_desc = CD3D11_TEXTURE2D_DESC(DXGI_FORMAT_R8G8B8A8_UNORM, EFB_WIDTH, EFB_HEIGHT, 1, 1, 0, D3D11_USAGE_STAGING, D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE);
hr = D3D::device->CreateTexture2D(&tex_desc, nullptr, &m_efb.color_cache_buf);
CHECK(hr == S_OK, "create EFB color cache buffer (hr=%#x)", hr);
D3D::SetDebugObjectName((ID3D11DeviceChild*)m_efb.color_cache_buf, "EFB color staging texture (used for Renderer::AccessEFB)");
D3D::SetDebugObjectName((ID3D11DeviceChild*)m_efb.color_cache_buf, "EFB color staging texture (used for g_renderer->AccessEFB)");
// Render buffer for AccessEFB (depth data)
tex_desc = CD3D11_TEXTURE2D_DESC(DXGI_FORMAT_R32_FLOAT, EFB_WIDTH, EFB_HEIGHT, 1, 1, D3D11_BIND_RENDER_TARGET);
@@ -101,20 +101,20 @@ void FramebufferManager::InitializeEFBCache()
CHECK(hr == S_OK, "create EFB depth cache read texture (hr=%#x)", hr);
m_efb.depth_cache_tex = new D3DTexture2D(buf, D3D11_BIND_RENDER_TARGET);
SAFE_RELEASE(buf);
D3D::SetDebugObjectName((ID3D11DeviceChild*)m_efb.depth_cache_tex->GetTex(), "EFB depth read texture (used in Renderer::AccessEFB)");
D3D::SetDebugObjectName((ID3D11DeviceChild*)m_efb.depth_cache_tex->GetRTV(), "EFB depth read texture render target view (used in Renderer::AccessEFB)");
D3D::SetDebugObjectName((ID3D11DeviceChild*)m_efb.depth_cache_tex->GetTex(), "EFB depth read texture (used in g_renderer->AccessEFB)");
D3D::SetDebugObjectName((ID3D11DeviceChild*)m_efb.depth_cache_tex->GetRTV(), "EFB depth read texture render target view (used in g_renderer->AccessEFB)");
// AccessEFB - Sysmem buffer used to retrieve the pixel data from depth_read_texture
tex_desc = CD3D11_TEXTURE2D_DESC(DXGI_FORMAT_R32_FLOAT, EFB_WIDTH, EFB_HEIGHT, 1, 1, 0, D3D11_USAGE_STAGING, D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE);
hr = D3D::device->CreateTexture2D(&tex_desc, nullptr, &m_efb.depth_cache_buf);
CHECK(hr == S_OK, "create EFB depth staging buffer (hr=%#x)", hr);
D3D::SetDebugObjectName((ID3D11DeviceChild*)m_efb.depth_cache_buf, "EFB depth cache buffer (used for Renderer::AccessEFB)");
D3D::SetDebugObjectName((ID3D11DeviceChild*)m_efb.depth_cache_buf, "EFB depth cache buffer (used for g_renderer->AccessEFB)");
}
FramebufferManager::FramebufferManager()
FramebufferManager::FramebufferManager(u32 target_width, u32 target_height)
{
m_target_width = std::max(Renderer::GetTargetWidth(), 1);
m_target_height = std::max(Renderer::GetTargetHeight(), 1);
m_target_width = std::max(target_width, 16u);
m_target_height = std::max(target_height, 16u);
DXGI_SAMPLE_DESC sample_desc;
sample_desc.Count = g_ActiveConfig.iMultisamples;
@@ -265,7 +265,7 @@ void XFBSource::CopyEFB(float Gamma)
D3D::context->RSSetViewports(1, &vp);
D3D::SetPointCopySampler();
D3D::drawShadedTexQuad(FramebufferManager::GetEFBDepthTexture()->GetSRV(), nullptr,
Renderer::GetTargetWidth(), Renderer::GetTargetHeight(),
g_renderer->GetTargetWidth(), g_renderer->GetTargetHeight(),
PixelShaderCache::GetColorCopyProgram(true), VertexShaderCache::GetSimpleVertexShader(),
VertexShaderCache::GetSimpleInputLayout(), GeometryShaderCache::GetCopyGeometryShader(), 1.0, 0, texWidth, texHeight);
D3D::context->OMSetRenderTargets(1,

View File

@@ -73,7 +73,7 @@ struct XFBSource : public XFBSourceBase
class FramebufferManager : public FramebufferManagerBase
{
public:
FramebufferManager();
FramebufferManager(u32 target_width, u32 target_height);
~FramebufferManager();
static D3DTexture2D* &GetEFBColorTexture();

View File

@@ -88,21 +88,21 @@ void HullDomainShaderCache::Init()
if (!File::Exists(File::GetUserPath(D_SHADERCACHE_IDX)))
File::CreateDir(File::GetUserPath(D_SHADERCACHE_IDX));
pKey_t gameid = (pKey_t)GetMurmurHash3(reinterpret_cast<const u8*>(SConfig::GetInstance().m_strGameID.data()), (u32)SConfig::GetInstance().m_strGameID.size(), 0);
pKey_t gameid = (pKey_t)GetMurmurHash3(reinterpret_cast<const u8*>(SConfig::GetInstance().GetGameID().data()), (u32)SConfig::GetInstance().GetGameID().size(), 0);
s_hulldomain_shaders = HDCache::Create(
gameid,
TESSELLATIONSHADERGEN_UID_VERSION,
"Ishiiruka.ts",
StringFromFormat("%s.ts", SConfig::GetInstance().m_strGameID.c_str())
StringFromFormat("%s.ts", SConfig::GetInstance().GetGameID().c_str())
);
std::string h_cache_filename = StringFromFormat("%sIDX11-%s-hs.cache", File::GetUserPath(D_SHADERCACHE_IDX).c_str(),
SConfig::GetInstance().m_strGameID.c_str());
SConfig::GetInstance().GetGameID().c_str());
HullShaderCacheInserter hinserter;
g_hs_disk_cache.OpenAndRead(h_cache_filename, hinserter);
std::string d_cache_filename = StringFromFormat("%sIDX11-%s-ds.cache", File::GetUserPath(D_SHADERCACHE_IDX).c_str(),
SConfig::GetInstance().m_strGameID.c_str());
SConfig::GetInstance().GetGameID().c_str());
DomainShaderCacheInserter dinserter;
g_ds_disk_cache.OpenAndRead(d_cache_filename, dinserter);
SETSTAT(stats.numDomainShadersCreated, 0);

View File

@@ -71,13 +71,16 @@ void PSTextureEncoder::Init()
D3D::SetDebugObjectName(m_encodeParams.get(), "efb encoder params buffer");
m_ready = true;
// Warm up with shader cache
std::string cache_filename = StringFromFormat("%sdx11-ENCODER-ps.cache", File::GetUserPath(D_SHADERCACHE_IDX).c_str());
m_shaderCache.OpenAndRead(cache_filename, ShaderCacheInserter(*this));
}
void PSTextureEncoder::Shutdown()
{
m_ready = false;
m_staticShaders.clear();
m_encoding_shaders.clear();
m_encodeParams.reset();
m_outStage.reset();
@@ -85,12 +88,17 @@ void PSTextureEncoder::Shutdown()
m_out.reset();
}
void PSTextureEncoder::Encode(u8* dest_ptr, u32 format, u32 native_width, u32 bytes_per_row, u32 num_blocks_y, u32 memory_stride,
bool is_depth_copy, bool isIntensity, bool scaleByHalf, const EFBRectangle& srcRect)
void PSTextureEncoder::Encode(u8* dst, const EFBCopyFormat& format, u32 native_width,
u32 bytes_per_row, u32 num_blocks_y, u32 memory_stride,
bool is_depth_copy, const EFBRectangle& src_rect, bool scale_by_half)
{
if (!m_ready) // Make sure we initialized OK
return;
auto shader = GetEncodingPixelShader(format);
if (shader == nullptr)
{
return;
}
HRESULT hr;
// Resolve MSAA targets before copying.
@@ -117,24 +125,24 @@ void PSTextureEncoder::Encode(u8* dest_ptr, u32 format, u32 native_width, u32 by
D3D::context->OMSetRenderTargets(1, &rtv, nullptr);
EFBEncodeParams params;
params.SrcLeft = srcRect.left;
params.SrcTop = srcRect.top;
params.SrcLeft = src_rect.left;
params.SrcTop = src_rect.top;
params.DestWidth = native_width;
params.ScaleFactor = scaleByHalf ? 2 : 1;
params.ScaleFactor = scale_by_half ? 2 : 1;
D3D::context->UpdateSubresource(m_encodeParams.get(), 0, nullptr, &params, 0, 0);
D3D::stateman->SetPixelConstants(m_encodeParams.get());
// Use linear filtering if (bScaleByHalf), use point filtering otherwise
if (scaleByHalf || g_ActiveConfig.iEFBScale != SCALE_1X)
if (scale_by_half || g_ActiveConfig.iEFBScale != SCALE_1X)
D3D::SetLinearCopySampler();
else
D3D::SetPointCopySampler();
D3D::drawShadedTexQuad(pEFB,
targetRect.AsRECT(),
Renderer::GetTargetWidth(),
Renderer::GetTargetHeight(),
SetStaticShader(format, is_depth_copy, isIntensity, scaleByHalf),
g_renderer->GetTargetWidth(),
g_renderer->GetTargetHeight(),
shader,
VertexShaderCache::GetSimpleVertexShader(),
VertexShaderCache::GetSimpleInputLayout());
@@ -151,8 +159,8 @@ void PSTextureEncoder::Encode(u8* dest_ptr, u32 format, u32 native_width, u32 by
u32 readStride = std::min(bytes_per_row, map.RowPitch);
for (unsigned int y = 0; y < num_blocks_y; ++y)
{
memcpy(dest_ptr, src, readStride);
dest_ptr += memory_stride;
memcpy(dst, src, readStride);
dst += memory_stride;
src += map.RowPitch;
}
@@ -166,60 +174,32 @@ void PSTextureEncoder::Encode(u8* dest_ptr, u32 format, u32 native_width, u32 by
FramebufferManager::GetEFBDepthTexture()->GetDSV());
}
ID3D11PixelShader* PSTextureEncoder::SetStaticShader(unsigned int dstFormat, bool is_depth_copy,
bool isIntensity, bool scaleByHalf)
ID3D11PixelShader* PSTextureEncoder::GetEncodingPixelShader(const EFBCopyFormat& format)
{
size_t scaledFetchNum = scaleByHalf ? 1 : 0;
size_t intensityNum = isIntensity ? 1 : 0;
size_t generatorNum = dstFormat;
auto iter = m_encoding_shaders.find(format);
if (iter != m_encoding_shaders.end())
return iter->second.get();
ComboKey key = MakeComboKey(dstFormat, is_depth_copy, isIntensity, scaleByHalf);
ComboMap::iterator it = m_staticShaders.find(key);
if (it == m_staticShaders.end())
D3DBlob bytecode;
const char* shader = TextureConversionShader::GenerateEncodingShader(format, API_D3D11);
if (!D3D::CompileShader(D3D::ShaderType::Pixel, shader, bytecode))
{
INFO_LOG(VIDEO, "Compiling efb encoding shader for dstFormat 0x%X, is_depth_copy %d, isIntensity %d, scaleByHalf %d",
dstFormat, is_depth_copy, isIntensity ? 1 : 0, scaleByHalf ? 1 : 0);
u32 format = dstFormat;
if (is_depth_copy)
{
format |= _GX_TF_ZTF;
if (dstFormat == 11)
format = GX_TF_Z16;
else if (format < GX_TF_Z8 || format > GX_TF_Z24X8)
format |= _GX_TF_CTF;
}
else
{
if (dstFormat > GX_TF_RGBA8 || (dstFormat < GX_TF_RGB565 && !isIntensity))
format |= _GX_TF_CTF;
}
D3DBlob bytecode;
const char* shader = TextureConversionShader::GenerateEncodingShader(format, API_D3D11);
if (!D3D::CompileShader(D3D::ShaderType::Pixel, shader, bytecode))
{
WARN_LOG(VIDEO, "EFB encoder shader for dstFormat 0x%X, is_depth_copy %d, isIntensity %d, scaleByHalf %d failed to compile",
dstFormat, is_depth_copy, isIntensity ? 1 : 0, scaleByHalf ? 1 : 0);
m_staticShaders[key] = nullptr;
return nullptr;
}
ID3D11PixelShader* newShader;
HRESULT hr = D3D::device->CreatePixelShader(bytecode.Data(), bytecode.Size(), nullptr, &newShader);
CHECK(SUCCEEDED(hr), "create efb encoder pixel shader");
char debugName[255] = {};
sprintf_s(debugName, "efb encoder pixel shader (dst:%d, is_depth_copy:%d, intensity:%d, scale:%d)",
dstFormat, is_depth_copy, isIntensity, scaleByHalf);
D3D::SetDebugObjectName(newShader, debugName);
it = m_staticShaders.emplace(key, D3D::PixelShaderPtr(newShader)).first;
PanicAlert("Failed to compile texture encoding shader.");
m_encoding_shaders[format] = nullptr;
return nullptr;
}
m_shaderCache.Append(format, bytecode.Data(), (u32)bytecode.Size());
return InsertShader(format, bytecode.Data(), (u32)bytecode.Size());
}
return it->second.get();
ID3D11PixelShader* PSTextureEncoder::InsertShader(const EFBCopyFormat &key, u8 const *data, u32 sz)
{
ID3D11PixelShader* newShader;
HRESULT hr = D3D::device->CreatePixelShader(data, sz, nullptr, &newShader);
CHECK(SUCCEEDED(hr), "create efb encoder pixel shader");
m_encoding_shaders.emplace(key, D3D::PixelShaderPtr(newShader));
return newShader;
}
}

View File

@@ -5,6 +5,7 @@
#pragma once
#include "Common/LinearDiskCache.h"
#include "VideoCommon/TextureConversionShader.h"
#include "VideoBackends/DX11/D3DPtr.h"
#include "VideoBackends/DX11/TextureEncoder.h"
@@ -18,10 +19,13 @@ public:
void Init();
void Shutdown();
void Encode(u8* dest_ptr, u32 format, u32 native_width, u32 bytes_per_row, u32 num_blocks_y, u32 memory_stride,
bool is_depth_copy, bool isIntensity, bool scaleByHalf, const EFBRectangle& srcRect);
void Encode(u8* dst, const EFBCopyFormat& format, u32 native_width,
u32 bytes_per_row, u32 num_blocks_y, u32 memory_stride,
bool is_depth_copy, const EFBRectangle& src_rect, bool scale_by_half);
private:
ID3D11PixelShader* GetEncodingPixelShader(const EFBCopyFormat& format);
ID3D11PixelShader* InsertShader(const EFBCopyFormat &key, u8 const *data, u32 sz);
bool m_ready;
D3D::Texture2dPtr m_out;
@@ -29,21 +33,24 @@ private:
D3D::Texture2dPtr m_outStage;
D3D::BufferPtr m_encodeParams;
ID3D11PixelShader* SetStaticShader(unsigned int dstFormat,
bool is_depth_copy, bool isIntensity, bool scaleByHalf);
std::map<EFBCopyFormat, D3D::PixelShaderPtr> m_encoding_shaders;
typedef unsigned int ComboKey; // Key for a shader combination
ComboKey MakeComboKey(unsigned int dstFormat,
bool is_depth_copy, bool isIntensity, bool scaleByHalf)
class ShaderCacheInserter : public LinearDiskCacheReader<EFBCopyFormat, u8>
{
return (dstFormat << 4) | (is_depth_copy << 2) | (isIntensity ? (1 << 1) : 0)
| (scaleByHalf ? (1 << 0) : 0);
}
public:
void Read(const EFBCopyFormat &key, const u8 *value, u32 value_size)
{
encoder_.InsertShader(key, value, value_size);
}
ShaderCacheInserter(PSTextureEncoder &encoder) : encoder_(encoder)
{}
private:
PSTextureEncoder& encoder_;
};
friend ShaderCacheInserter;
typedef std::map<ComboKey, D3D::PixelShaderPtr> ComboMap;
LinearDiskCache<EFBCopyFormat, u8> m_shaderCache;
ComboMap m_staticShaders;
};
}

View File

@@ -8,6 +8,7 @@
#include <string>
#include <strsafe.h>
#include <array>
#include <tuple>
#include "Common/CommonTypes.h"
#include "Common/FileUtil.h"
@@ -46,10 +47,6 @@
namespace DX11
{
static u32 s_last_multisamples = 0;
static int s_last_stereo_mode = STEREO_OFF;
static bool s_last_xfb_mode = false;
static Television s_television;
D3D::BlendStatePtr clearblendstates[4];
@@ -82,11 +79,11 @@ struct
StateCache gx_state_cache;
static void SetupDeviceObjects()
void Renderer::SetupDeviceObjects()
{
s_television.Init();
g_framebuffer_manager = std::make_unique<FramebufferManager>();
g_framebuffer_manager = std::make_unique<FramebufferManager>(m_target_width, m_target_height);
HRESULT hr;
D3D11_DEPTH_STENCIL_DESC ddesc;
@@ -254,26 +251,15 @@ void Renderer::PrepareFrameDumpBuffer(u32 width, u32 height)
Renderer::Renderer(void *&window_handle)
{
D3D::Create((HWND)window_handle);
m_backbuffer_width = D3D::GetBackBufferWidth();
m_backbuffer_height = D3D::GetBackBufferHeight();
s_backbuffer_width = D3D::GetBackBufferWidth();
s_backbuffer_height = D3D::GetBackBufferHeight();
FramebufferManagerBase::SetLastXfbWidth(MAX_XFB_WIDTH);
FramebufferManagerBase::SetLastXfbHeight(MAX_XFB_HEIGHT);
UpdateDrawRectangle();
s_last_multisamples = g_ActiveConfig.iMultisamples;
s_last_efb_scale = g_ActiveConfig.iEFBScale;
s_last_stereo_mode = g_ActiveConfig.iStereoMode;
s_last_xfb_mode = g_ActiveConfig.bUseRealXFB;
CalculateTargetSize();
PixelShaderManager::SetEfbScaleChanged();
SetupDeviceObjects();
m_post_processor = std::make_unique<D3DPostProcessor>();
if (!m_post_processor->Initialize())
PanicAlert("D3D: Failed to initialize post processor.");
m_last_multisamples = g_ActiveConfig.iMultisamples;
m_last_efb_scale = g_ActiveConfig.iEFBScale;
m_last_stereo_mode = g_ActiveConfig.iStereoMode;
m_last_xfb_mode = g_ActiveConfig.bUseRealXFB;
// Setup GX pipeline state
gx_state.blend.blend_enable = false;
@@ -295,18 +281,33 @@ Renderer::Renderer(void *&window_handle)
gx_state.raster.cull_mode = D3D11_CULL_NONE;
m_3d_vision_texture = nullptr;
m_frame_dump_render_texture = nullptr;
m_frame_dump_staging_texture.reset();
}
void Renderer::Init()
{
UpdateDrawRectangle();
FramebufferManagerBase::SetLastXfbWidth(MAX_XFB_WIDTH);
FramebufferManagerBase::SetLastXfbHeight(MAX_XFB_HEIGHT);
CalculateTargetSize();
PixelShaderManager::SetEfbScaleChanged();
SetupDeviceObjects();
m_post_processor = std::make_unique<D3DPostProcessor>();
if (!m_post_processor->Initialize())
PanicAlert("D3D: Failed to initialize post processor.");
// Clear EFB textures
float ClearColor[4] = { 0.f, 0.f, 0.f, 1.f };
D3D::context->ClearRenderTargetView(FramebufferManager::GetEFBColorTexture()->GetRTV(), ClearColor);
D3D::context->ClearDepthStencilView(FramebufferManager::GetEFBDepthTexture()->GetDSV(), D3D11_CLEAR_DEPTH, 1.f, 0);
D3D11_VIEWPORT vp = CD3D11_VIEWPORT(0.f, 0.f, (float)s_target_width, (float)s_target_height);
D3D11_VIEWPORT vp = CD3D11_VIEWPORT(0.f, 0.f, (float)m_target_width, (float)m_target_height);
D3D::context->RSSetViewports(1, &vp);
D3D::context->OMSetRenderTargets(1, &FramebufferManager::GetEFBColorTexture()->GetRTV(), FramebufferManager::GetEFBDepthTexture()->GetDSV());
D3D::BeginFrame();
m_3d_vision_texture = nullptr;
m_frame_dump_render_texture = nullptr;
m_frame_dump_staging_texture.reset();
}
Renderer::~Renderer()
@@ -364,14 +365,11 @@ bool Renderer::CheckForResize()
// Get the top-left corner of the client area in screen coordinates
POINT originPoint = { 0, 0 };
ClientToScreen(D3D::hWnd, &originPoint);
window_rc.left = originPoint.x;
window_rc.right = originPoint.x + client_width;
window_rc.top = originPoint.y;
window_rc.bottom = originPoint.y + client_height;
g_renderer->SetWindowRectangle(originPoint.x, originPoint.x + client_width, originPoint.y, originPoint.y + client_height);
// Sanity check
if ((client_width != Renderer::GetBackbufferWidth() ||
client_height != Renderer::GetBackbufferHeight()) &&
if ((client_width != g_renderer->GetBackbufferWidth() ||
client_height != g_renderer->GetBackbufferHeight()) &&
client_width >= 4 && client_height >= 4)
{
return true;
@@ -380,9 +378,9 @@ bool Renderer::CheckForResize()
return false;
}
void Renderer::SetScissorRect(const TargetRectangle& rc)
void Renderer::SetScissorRect(const EFBRectangle& rc)
{
D3D::context->RSSetScissorRects(1, rc.AsRECT());
D3D::context->RSSetScissorRects(1, ConvertEFBRectangle(rc).AsRECT());
}
void Renderer::SetColorMask()
@@ -681,7 +679,7 @@ void Renderer::SetBlendMode(bool forceUpdate)
// This function has the final picture. We adjust the aspect ratio here.
void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, const EFBRectangle& rc, u64 ticks, float Gamma)
{
if ((!XFBWrited && !g_ActiveConfig.RealXFBEnabled()) || !fbWidth || !fbHeight)
if ((!m_xfb_written && !g_ActiveConfig.RealXFBEnabled()) || !fbWidth || !fbHeight)
{
Core::Callback_VideoCopiedToXFB(false);
return;
@@ -706,8 +704,8 @@ void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, co
D3D::context->ClearRenderTargetView(D3D::GetBackBuffer()->GetRTV(), ClearColor);
// Copy the framebuffer to screen.
const TargetSize dst_size = { s_target_width, s_target_height };
DrawFrame(target_rc, rc, xfbAddr, xfbSourceList, xfbCount, D3D::GetBackBuffer(), dst_size, fbWidth, fbStride, fbHeight, Gamma);
const TargetSize dst_size = { m_target_width, m_target_height };
DrawFrame(targetRc, rc, xfbAddr, xfbSourceList, xfbCount, D3D::GetBackBuffer(), dst_size, fbWidth, fbStride, fbHeight, Gamma);
// Dump frames
if (IsFrameDumping())
@@ -729,7 +727,7 @@ void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, co
const bool windowResized = CheckForResize();
bool xfbchanged = s_last_xfb_mode != g_ActiveConfig.bUseRealXFB;
bool xfbchanged = m_last_xfb_mode != g_ActiveConfig.bUseRealXFB;
if (FramebufferManagerBase::LastXfbWidth() != fbStride || FramebufferManagerBase::LastXfbHeight() != fbHeight)
{
@@ -747,38 +745,38 @@ void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, co
if (CalculateTargetSize()
|| xfbchanged
|| windowResized
|| s_last_efb_scale != g_ActiveConfig.iEFBScale
|| s_last_multisamples != g_ActiveConfig.iMultisamples
|| s_last_stereo_mode != g_ActiveConfig.iStereoMode)
|| m_last_efb_scale != g_ActiveConfig.iEFBScale
|| m_last_multisamples != g_ActiveConfig.iMultisamples
|| m_last_stereo_mode != g_ActiveConfig.iStereoMode)
{
s_last_xfb_mode = g_ActiveConfig.bUseRealXFB;
s_last_multisamples = g_ActiveConfig.iMultisamples;
m_last_xfb_mode = g_ActiveConfig.bUseRealXFB;
m_last_multisamples = g_ActiveConfig.iMultisamples;
PixelShaderCache::InvalidateMSAAShaders();
if (windowResized)
{
// TODO: Aren't we still holding a reference to the back buffer right now?
D3D::Reset();
s_backbuffer_width = D3D::GetBackBufferWidth();
s_backbuffer_height = D3D::GetBackBufferHeight();
m_backbuffer_width = D3D::GetBackBufferWidth();
m_backbuffer_height = D3D::GetBackBufferHeight();
}
UpdateDrawRectangle();
s_last_efb_scale = g_ActiveConfig.iEFBScale;
m_last_efb_scale = g_ActiveConfig.iEFBScale;
PixelShaderManager::SetEfbScaleChanged();
D3D::context->OMSetRenderTargets(1, &D3D::GetBackBuffer()->GetRTV(), nullptr);
g_framebuffer_manager.reset();
g_framebuffer_manager = std::make_unique<FramebufferManager>();
g_framebuffer_manager = std::make_unique<FramebufferManager>(m_target_width, m_target_height);
float clear_col[4] = { 0.f, 0.f, 0.f, 1.f };
D3D::context->ClearRenderTargetView(FramebufferManager::GetEFBColorTexture()->GetRTV(), clear_col);
D3D::context->ClearDepthStencilView(FramebufferManager::GetEFBDepthTexture()->GetDSV(), D3D11_CLEAR_DEPTH, 1.f, 0);
if (s_last_stereo_mode != g_ActiveConfig.iStereoMode)
if (m_last_stereo_mode != g_ActiveConfig.iStereoMode)
{
s_last_stereo_mode = g_ActiveConfig.iStereoMode;
m_last_stereo_mode = g_ActiveConfig.iStereoMode;
m_post_processor->SetReloadFlag();
}
}
@@ -1018,11 +1016,6 @@ void Renderer::SetLogicOpMode()
}
}
void Renderer::SetDitherMode()
{
// TODO: Set dither mode to bpmem.blendmode.dither
}
void Renderer::SetSamplerState(int stage, int texindex, bool custom_tex)
{
const FourTexUnits &tex = bpmem.tex[texindex];
@@ -1075,12 +1068,12 @@ u16 Renderer::BBoxRead(int index)
if (index < 2)
{
// left/right
value = value * EFB_WIDTH / s_target_width;
value = value * EFB_WIDTH / m_target_width;
}
else
{
// up/down
value = value * EFB_HEIGHT / s_target_height;
value = value * EFB_HEIGHT / m_target_height;
}
if (index & 1)
value++; // fix max values to describe the outer border
@@ -1095,11 +1088,11 @@ void Renderer::BBoxWrite(int index, u16 _value)
value--;
if (index < 2)
{
value = value * s_target_width / EFB_WIDTH;
value = value * m_target_width / EFB_WIDTH;
}
else
{
value = value * s_target_height / EFB_HEIGHT;
value = value * m_target_height / EFB_HEIGHT;
}
BBox::Set(index, value);
}
@@ -1129,7 +1122,7 @@ void Renderer::DrawEFB(const TargetRectangle& t_rc, const EFBRectangle& source_r
TargetRectangle scaled_source_rc = Renderer::ConvertEFBRectangle(source_rc);
TargetRectangle target_rc = { t_rc.left, t_rc.top, t_rc.right, t_rc.bottom };
D3DTexture2D* tex = FramebufferManager::GetResolvedEFBColorTexture();
TargetSize tex_size(s_target_width, s_target_height);
TargetSize tex_size(m_target_width, m_target_height);
D3DTexture2D* blit_depth_tex = nullptr;
// Post processing active?
if (m_post_processor->ShouldTriggerOnSwap())
@@ -1220,7 +1213,7 @@ void Renderer::BlitScreen(TargetRectangle dst_rect, TargetRectangle src_rect, Ta
if (g_ActiveConfig.iStereoMode == STEREO_SBS || g_ActiveConfig.iStereoMode == STEREO_TAB)
{
TargetRectangle leftRc, rightRc;
ConvertStereoRectangle(dst_rect, leftRc, rightRc);
std::tie(leftRc, rightRc) = ConvertStereoRectangle(dst_rect);
m_post_processor->BlitScreen(leftRc, dst_size, reinterpret_cast<uintptr_t>(dst_texture),
src_rect, src_size, reinterpret_cast<uintptr_t>(src_texture), reinterpret_cast<uintptr_t>(depth_texture), 0, Gamma);
@@ -1239,8 +1232,8 @@ void Renderer::BlitScreen(TargetRectangle dst_rect, TargetRectangle src_rect, Ta
leftRc.bottom = dst_rect.bottom;
TargetRectangle rightRc;
rightRc.left = dst_rect.left + s_backbuffer_width;
rightRc.right = dst_rect.right + s_backbuffer_width;
rightRc.left = dst_rect.left + m_backbuffer_width;
rightRc.right = dst_rect.right + m_backbuffer_width;
rightRc.top = dst_rect.top;
rightRc.bottom = dst_rect.bottom;
TargetSize side_size = { dst_size.width * 2, dst_size .height};
@@ -1290,7 +1283,7 @@ void Renderer::DumpFrame(const EFBRectangle& source_rc, u32 xfb_addr,
src = D3D::GetBackBuffer();
src_width = GetTargetRectangle().GetWidth();
src_height = GetTargetRectangle().GetHeight();
source_box = GetScreenshotSourceBox(target_rc, src_width, src_height);
source_box = GetScreenshotSourceBox(m_target_rectangle, src_width, src_height);
}
PrepareFrameDumpBuffer(src_width, src_height);

View File

@@ -18,14 +18,13 @@ class Renderer : public ::Renderer
public:
Renderer(void *&window_handle);
~Renderer();
void Init() override;
void SetColorMask() override;
void SetBlendMode(bool forceUpdate) override;
void SetScissorRect(const TargetRectangle& rc) override;
void SetScissorRect(const EFBRectangle& rc) override;
void SetGenerationMode() override;
void SetDepthMode() override;
void SetLogicOpMode() override;
void SetDitherMode() override;
void SetSamplerState(int stage, int texindex, bool custom_tex) override;
void SetInterlacingMode() override;
void SetViewport() override;
@@ -55,7 +54,7 @@ public:
void ClearScreen(const EFBRectangle& rc, bool colorEnable, bool alphaEnable, bool zEnable, u32 color, u32 z) override;
void ReinterpretPixelData(unsigned int convtype) override;
static bool CheckForResize();
bool CheckForResize();
private:
// Draw either the EFB, or specified XFB sources to the currently-bound framebuffer.
@@ -77,6 +76,8 @@ private:
void PrepareFrameDumpRenderTexture(u32 width, u32 height);
void PrepareFrameDumpBuffer(u32 width, u32 height);
void Create3DVisionTexture(u32 width, u32 height);
void SetupDeviceObjects();
D3DTexture2D* m_frame_dump_render_texture = nullptr;
D3D::Texture2dPtr m_frame_dump_staging_texture;
D3DTexture2D* m_3d_vision_texture = nullptr;
@@ -86,6 +87,9 @@ private:
u32 m_frame_dump_staging_texture_height = 0;
u32 m_3d_vision_texture_width = 0;
u32 m_3d_vision_texture_height = 0;
u32 m_last_multisamples = 0;
int m_last_stereo_mode = 0;
bool m_last_xfb_mode = false;
};
}

View File

@@ -18,14 +18,13 @@
#include "VideoCommon/ImageWrite.h"
#include "VideoCommon/RenderBase.h"
#include "VideoCommon/VideoConfig.h"
#include "VideoCommon/TextureScalerCommon.h"
namespace DX11
{
static std::unique_ptr<TextureEncoder> s_encoder;
static std::unique_ptr<TextureDecoder> s_decoder;
static std::unique_ptr<TextureScaler> s_scaler;
const size_t MAX_COPY_BUFFERS = 33;
D3D::BufferPtr efbcopycbuf[MAX_COPY_BUFFERS];
@@ -101,6 +100,11 @@ void TextureCache::LoadLut(u32 lutFmt, void* addr, u32 size)
s_decoder->LoadLut(lutFmt, addr, size);
}
bool TextureCache::SupportsGPUTextureDecode(TextureFormat format, TlutFormat palette_format)
{
return s_decoder->FormatSupported(format);
}
void TextureCache::TCacheEntry::CopyRectangleFromTexture(
const TCacheEntryBase* source,
const MathUtil::Rectangle<int> &srcrect,
@@ -204,91 +208,22 @@ void TextureCache::TCacheEntry::LoadMaterialMap(const u8* src, u32 width, u32 he
swap_rg,
convertrgb565);
}
void TextureCache::TCacheEntry::Load(const u8* src, u32 width, u32 height, u32 expandedWidth,
u32 expandedHeight, const s32 texformat, const u32 tlutaddr, const TlutFormat tlutfmt, u32 level)
bool TextureCache::TCacheEntry::DecodeTextureOnGPU(u32 dst_level, const u8* data,
u32 data_size, TextureFormat format, u32 width, u32 height,
u32 aligned_width, u32 aligned_height, u32 row_stride,
const u8* palette, TlutFormat palette_format)
{
bool need_cpu_decode = is_scaled;
if (!need_cpu_decode)
{
need_cpu_decode = !s_decoder->Decode(
src,
TexDecoder_GetTextureSizeInBytes(expandedWidth, expandedHeight, texformat),
texformat,
width,
height,
level,
*texture);
}
if (need_cpu_decode)
{
u8* data = g_texture_cache->GetTemporalBuffer();
TexDecoder_Decode(
data,
src,
expandedWidth,
expandedHeight,
texformat,
tlutaddr,
tlutfmt,
PC_TEX_FMT_RGBA32 == config.pcformat,
compressed);
if (is_scaled)
{
data = (u8*)s_scaler->Scale((u32*)data, expandedWidth, height);
width *= g_ActiveConfig.iTexScalingFactor;
height *= g_ActiveConfig.iTexScalingFactor;
expandedWidth *= g_ActiveConfig.iTexScalingFactor;
}
D3D::ReplaceTexture2D(
texture->GetTex(),
data,
width,
height,
expandedWidth,
level,
usage,
DXGI_format,
swap_rg,
convertrgb565);
}
}
void TextureCache::TCacheEntry::LoadFromTmem(const u8* ar_src, const u8* gb_src, u32 width, u32 height,
u32 expanded_width, u32 expanded_Height, u32 level)
{
bool need_cpu_decode = is_scaled;
if (!need_cpu_decode)
{
need_cpu_decode = !s_decoder->DecodeRGBAFromTMEM(ar_src, gb_src, width, height, *texture);
}
if (need_cpu_decode)
{
u8* data = g_texture_cache->GetTemporalBuffer();
TexDecoder_DecodeRGBA8FromTmem(
(u32*)data,
ar_src,
gb_src,
expanded_width,
expanded_Height);
if (is_scaled)
{
data = (u8*)s_scaler->Scale((u32*)data, expanded_width, height);
width *= g_ActiveConfig.iTexScalingFactor;
height *= g_ActiveConfig.iTexScalingFactor;
expanded_width *= g_ActiveConfig.iTexScalingFactor;
}
D3D::ReplaceTexture2D(
texture->GetTex(),
data,
width,
height,
expanded_width,
level,
usage,
DXGI_format,
swap_rg,
convertrgb565);
}
return s_decoder->Decode(
data,
data_size,
format,
width,
height,
aligned_width,
aligned_height,
dst_level,
*texture);
}
PC_TexFormat TextureCache::GetNativeTextureFormat(const s32 texformat, const TlutFormat tlutfmt, u32 width, u32 height)
@@ -450,7 +385,7 @@ void TextureCache::TCacheEntry::FromRenderTarget(bool is_depth_copy, const EFBRe
// Create texture copy
D3D::drawShadedTexQuad(
efb_texture_srv,
&sourcerect, Renderer::GetTargetWidth(), Renderer::GetTargetHeight(),
&sourcerect, g_renderer->GetTargetWidth(), g_renderer->GetTargetHeight(),
is_depth_copy ? PixelShaderCache::GetDepthMatrixProgram(multisampled) : PixelShaderCache::GetColorMatrixProgram(multisampled),
VertexShaderCache::GetSimpleVertexShader(),
VertexShaderCache::GetSimpleInputLayout(),
@@ -462,21 +397,12 @@ void TextureCache::TCacheEntry::FromRenderTarget(bool is_depth_copy, const EFBRe
D3D::stateman->SetTextureByMask(texture_mask, texture->GetSRV());
}
void TextureCache::CopyEFB(u8* dst, u32 format, u32 native_width, u32 bytes_per_row, u32 num_blocks_y, u32 memory_stride,
bool is_depth_copy, const EFBRectangle& srcRect,
bool isIntensity, bool scaleByHalf)
void TextureCache::CopyEFB(u8* dst, const EFBCopyFormat& format, u32 native_width,
u32 bytes_per_row, u32 num_blocks_y, u32 memory_stride,
bool is_depth_copy, const EFBRectangle& src_rect, bool scale_by_half)
{
s_encoder->Encode(
dst,
format,
native_width,
bytes_per_row,
num_blocks_y,
memory_stride,
is_depth_copy,
isIntensity,
scaleByHalf,
srcRect);
s_encoder->Encode(dst, format, native_width, bytes_per_row, num_blocks_y, memory_stride,
is_depth_copy, src_rect, scale_by_half);
}
bool TextureCache::Palettize(TCacheEntryBase* entry, const TCacheEntryBase* base_entry)
@@ -512,7 +438,6 @@ TextureCache::TextureCache()
s_encoder->Init();
s_decoder = std::make_unique<CSTextureDecoder>();
s_decoder->Init();
s_scaler = std::make_unique<TextureScaler>();
}
TextureCache::~TextureCache()
@@ -525,7 +450,6 @@ TextureCache::~TextureCache()
s_decoder->Shutdown();
s_decoder.reset();
s_scaler.reset();
}
}

View File

@@ -40,13 +40,12 @@ private:
void Load(const u8* src, u32 width, u32 height,
u32 expanded_width, u32 level) override;
void LoadMaterialMap(const u8* src, u32 width, u32 height, u32 level) override;
void Load(const u8* src, u32 width, u32 height, u32 expandedWidth,
u32 expandedHeight, const s32 texformat, const u32 tlutaddr, const TlutFormat tlutfmt, u32 level) override;
void LoadFromTmem(const u8* ar_src, const u8* gb_src, u32 width, u32 height,
u32 expanded_width, u32 expanded_Height, u32 level) override;
void FromRenderTarget(bool is_depth_copy, const EFBRectangle& srcRect,
bool scaleByHalf, unsigned int cbufid, const float *colmat, u32 width, u32 height) override;
bool DecodeTextureOnGPU(u32 dst_level, const u8* data,
u32 data_size, TextureFormat format, u32 width, u32 height,
u32 aligned_width, u32 aligned_height, u32 row_stride,
const u8* palette, TlutFormat palette_format) override;
bool SupportsMaterialMap() const override
{
return nrm_texture != nullptr;
@@ -63,11 +62,12 @@ private:
TextureCache::TCacheEntryBase* CreateTexture(const TCacheEntryConfig& config);
void CopyEFB(u8* dst, u32 format, u32 native_width, u32 bytes_per_row, u32 num_blocks_y, u32 memory_stride,
bool is_depth_copy, const EFBRectangle& srcRect,
bool isIntensity, bool scaleByHalf) override;
void CopyEFB(u8* dst, const EFBCopyFormat& format, u32 native_width, u32 bytes_per_row,
u32 num_blocks_y, u32 memory_stride, bool is_depth_copy,
const EFBRectangle& src_rect, bool scale_by_half) override;
bool Palettize(TCacheEntryBase* entry, const TCacheEntryBase* base_entry) override;
void LoadLut(u32 lutFmt, void* addr, u32 size) override;
bool SupportsGPUTextureDecode(TextureFormat format, TlutFormat palette_format) override;
bool CompileShaders() override
{
return true;

View File

@@ -83,8 +83,9 @@ public:
virtual void Init() = 0;
virtual void Shutdown() = 0;
virtual void Encode(u8* dest_ptr, u32 format, u32 native_width, u32 bytes_per_row, u32 num_blocks_y, u32 memory_stride,
bool is_depth_copy, bool bIsIntensityFmt, bool bScaleByHalf, const EFBRectangle& source) = 0;
virtual void Encode(u8* dst, const EFBCopyFormat& format, u32 native_width,
u32 bytes_per_row, u32 num_blocks_y, u32 memory_stride,
bool is_depth_copy, const EFBRectangle& src_rect, bool scale_by_half) = 0;
};
@@ -99,8 +100,7 @@ public:
virtual void Init() = 0;
virtual void Shutdown() = 0;
virtual bool FormatSupported(u32 srcFmt) = 0;
virtual bool Decode(const u8* src, u32 srcsize, u32 srcFmt, u32 w, u32 h, u32 levels, D3DTexture2D& dstTexture) = 0;
virtual bool DecodeRGBAFromTMEM(u8 const * ar_src, u8 const * bg_src, u32 width, u32 height, D3DTexture2D& dstTexture) = 0;
virtual bool Decode(const u8* src, u32 srcsize, u32 srcFmt, u32 w, u32 h, u32 expandedw, u32 expandedh, u32 levels, D3DTexture2D& dstTexture) = 0;
virtual bool Depalettize(D3DTexture2D& dstTexture, D3DTexture2D& srcTexture, BaseType baseType, u32 width, u32 height) = 0;
virtual void LoadLut(u32 lutFmt, void* addr, u32 size) = 0;

View File

@@ -60,8 +60,8 @@ VertexManager::VertexManager()
{
LocalVBuffer.resize(MAXVBUFFERSIZE);
s_pCurBufferPointer = s_pBaseBufferPointer = &LocalVBuffer[0];
s_pEndBufferPointer = s_pBaseBufferPointer + LocalVBuffer.size();
m_pCurBufferPointer = m_pBaseBufferPointer = &LocalVBuffer[0];
m_pEndBufferPointer = m_pBaseBufferPointer + LocalVBuffer.size();
LocalIBuffer.resize(MAXIBUFFERSIZE);
m_index_buffer_start = &LocalIBuffer[0];
@@ -76,7 +76,7 @@ VertexManager::~VertexManager()
void VertexManager::PrepareDrawBuffers(u32 stride)
{
D3D11_MAPPED_SUBRESOURCE map;
u32 vertexBufferSize = u32(s_pCurBufferPointer - s_pBaseBufferPointer);
u32 vertexBufferSize = u32(m_pCurBufferPointer - m_pBaseBufferPointer);
u32 indexBufferSize = IndexGenerator::GetIndexLen() * sizeof(u16);
u32 totalBufferSize = vertexBufferSize + indexBufferSize;
@@ -99,7 +99,7 @@ void VertexManager::PrepareDrawBuffers(u32 stride)
D3D::context->Map(m_buffers[m_currentBuffer].get(), 0, MapType, 0, &map);
u8* mappedData = reinterpret_cast<u8*>(map.pData);
memcpy(mappedData + m_vertexDrawOffset, s_pBaseBufferPointer, vertexBufferSize);
memcpy(mappedData + m_vertexDrawOffset, m_pBaseBufferPointer, vertexBufferSize);
memcpy(mappedData + m_indexDrawOffset, m_index_buffer_start, indexBufferSize);
D3D::context->Unmap(m_buffers[m_currentBuffer].get(), 0);
@@ -119,7 +119,7 @@ void VertexManager::Draw(UINT stride)
u32 baseVertex = m_vertexDrawOffset / stride;
u32 startIndex = m_indexDrawOffset / sizeof(u16);
if (current_primitive_type == PRIMITIVE_TRIANGLES)
if (m_current_primitive_type == PRIMITIVE_TRIANGLES)
{
auto pt = HullDomainShaderCache::GetActiveHullShader() != nullptr ?
D3D11_PRIMITIVE_TOPOLOGY_3_CONTROL_POINT_PATCHLIST :
@@ -129,7 +129,7 @@ void VertexManager::Draw(UINT stride)
}
else
{
D3D::stateman->SetPrimitiveTopology(current_primitive_type == PRIMITIVE_LINES ? D3D11_PRIMITIVE_TOPOLOGY_LINELIST : D3D11_PRIMITIVE_TOPOLOGY_POINTLIST);
D3D::stateman->SetPrimitiveTopology(m_current_primitive_type == PRIMITIVE_LINES ? D3D11_PRIMITIVE_TOPOLOGY_LINELIST : D3D11_PRIMITIVE_TOPOLOGY_POINTLIST);
static_cast<Renderer*>(g_renderer.get())->ApplyCullDisable();
}
@@ -137,7 +137,7 @@ void VertexManager::Draw(UINT stride)
D3D::context->DrawIndexed(indices, startIndex, baseVertex);
INCSTAT(stats.thisFrame.numDrawCalls);
if (current_primitive_type != PRIMITIVE_TRIANGLES)
if (m_current_primitive_type != PRIMITIVE_TRIANGLES)
{
static_cast<Renderer*>(g_renderer.get())->RestoreCull();
}
@@ -162,7 +162,7 @@ void VertexManager::vFlush(bool useDstAlpha)
{
return;
}
if (g_ActiveConfig.iStereoMode > 0 || current_primitive_type != PrimitiveType::PRIMITIVE_TRIANGLES)
if (g_ActiveConfig.iStereoMode > 0 || m_current_primitive_type != PrimitiveType::PRIMITIVE_TRIANGLES)
{
if (!GeometryShaderCache::TestShader())
{
@@ -194,7 +194,7 @@ void VertexManager::vFlush(bool useDstAlpha)
void VertexManager::ResetBuffer(u32 stride)
{
s_pCurBufferPointer = s_pBaseBufferPointer;
m_pCurBufferPointer = m_pBaseBufferPointer;
IndexGenerator::Start(m_index_buffer_start);
}

View File

@@ -105,7 +105,7 @@ void VideoBackend::InitBackendInfo()
g_Config.backend_info.bSupportsDepthClamp = true;
g_Config.backend_info.bSupportsMultithreading = false;
g_Config.backend_info.bSupportsValidationLayer = false;
g_Config.backend_info.bSupportsReversedDepthRange = true;
g_Config.backend_info.bSupportsReversedDepthRange = false;
g_Config.backend_info.bSupportsInternalResolutionFrameDumps = true;
g_Config.backend_info.bSupportsAsyncShaderCompilation = true;
IDXGIFactory* factory;
@@ -144,7 +144,7 @@ void VideoBackend::InitBackendInfo()
g_Config.backend_info.bSupportsGSInstancing = shader_model_5_supported;
g_Config.backend_info.bSupportsTessellation = shader_model_5_supported;
g_Config.backend_info.bSupportsSSAA = shader_model_5_supported;
g_Config.backend_info.bSupportsComputeTextureDecoding = shader_model_5_supported;
g_Config.backend_info.bSupportsGPUTextureDecoding = shader_model_5_supported;
g_Config.backend_info.bSupportsComputeTextureEncoding = shader_model_5_supported;
g_Config.backend_info.MaxTextureSize = DX11::D3D::GetMaxTextureSize(DX11::D3D::GetFeatureLevel(ad));
}
@@ -173,6 +173,7 @@ void VideoBackend::Video_Prepare()
{
// internal interfaces
g_renderer = std::make_unique<Renderer>(m_window_handle);
g_renderer->Init();
g_texture_cache = std::make_unique<TextureCache>();
g_vertex_manager = std::make_unique<VertexManager>();
g_perf_query = std::make_unique<PerfQuery>();

View File

@@ -58,11 +58,11 @@ void FramebufferManager::InitializeEFBCache()
}
FramebufferManager::FramebufferManager()
FramebufferManager::FramebufferManager(u32 target_width, u32 target_height)
{
m_target_width = std::max(target_width, 16u);
m_target_height = std::max(target_height, 16u);
s_efb.depth_textures_supported = true;
m_target_width = std::max(Renderer::GetTargetWidth(), 1);
m_target_height = std::max(Renderer::GetTargetHeight(), 1);
s_efb.color_surface_Format = D3DFMT_A8R8G8B8;
// EFB color texture - primary render target
@@ -212,8 +212,8 @@ void XFBSource::CopyEFB(float Gamma)
D3D::drawShadedTexQuad(
FramebufferManager::GetEFBColorTexture(),
nullptr,
Renderer::GetTargetWidth(),
Renderer::GetTargetHeight(),
g_renderer->GetTargetWidth(),
g_renderer->GetTargetHeight(),
texWidth,
texHeight,
PixelShaderCache::GetColorCopyProgram(0),
@@ -316,8 +316,8 @@ void FramebufferManager::PopulateEFBDepthCache()
D3D::drawShadedTexQuad(
read_texture,
nullptr,
Renderer::GetTargetWidth(),
Renderer::GetTargetHeight(),
g_renderer->GetTargetWidth(),
g_renderer->GetTargetHeight(),
EFB_WIDTH, EFB_HEIGHT,
PixelShaderCache::GetDepthMatrixProgram(0, bformat != FOURCC_RAWZ),
VertexShaderCache::GetSimpleVertexShader(0));

View File

@@ -60,7 +60,7 @@ struct XFBSource : public XFBSourceBase
class FramebufferManager : public FramebufferManagerBase
{
public:
FramebufferManager();
FramebufferManager(u32 target_width, u32 target_height);
~FramebufferManager();
static LPDIRECT3DTEXTURE9 GetEFBColorTexture()

View File

@@ -48,22 +48,13 @@
namespace DX9
{
static int s_fps = 0;
static LPDIRECT3DSURFACE9 m_screen_shoot_mem_surface = nullptr;
static u32 s_blendMode;
static u32 s_LastAA;
static bool IS_AMD;
static float m_fMaxPointSize;
static bool s_vsync;
static bool s_b3D_RightFrame = false;
static LPDIRECT3DSURFACE9 ScreenShootMEMSurface = NULL;
static bool s_last_fullscreen_mode;
void SetupDeviceObjects()
void Renderer::SetupDeviceObjects()
{
D3D::font.Init();
VertexLoaderManager::Init();
g_framebuffer_manager = std::make_unique<FramebufferManager>();
g_framebuffer_manager = std::make_unique<FramebufferManager>(m_target_width, m_target_height);
VertexShaderManager::Dirty();
PixelShaderManager::Dirty();
@@ -78,11 +69,11 @@ void SetupDeviceObjects()
}
// Kill off all POOL_DEFAULT device objects.
void TeardownDeviceObjects()
void Renderer::TeardownDeviceObjects()
{
if (ScreenShootMEMSurface)
ScreenShootMEMSurface->Release();
ScreenShootMEMSurface = NULL;
if (m_screen_shoot_mem_surface != nullptr)
m_screen_shoot_mem_surface->Release();
m_screen_shoot_mem_surface = nullptr;
D3D::dev->SetRenderTarget(0, D3D::GetBackBufferSurface());
D3D::dev->SetDepthStencilSurface(D3D::GetBackBufferDepthSurface());
g_framebuffer_manager.reset();
@@ -100,9 +91,8 @@ void TeardownDeviceObjects()
Renderer::Renderer(void *&window_handle)
{
int fullScreenRes, w_temp, h_temp;
s_blendMode = 0;
// Multisample Anti-aliasing hasn't been implemented yet use supersamling instead
int backbuffer_ms_mode = 0;
int backbuffer_mm_mode = 0;
RECT client;
GetClientRect((HWND)window_handle, &client);
@@ -119,28 +109,44 @@ Renderer::Renderer(void *&window_handle)
fullScreenRes = 0;
D3D::Create(g_ActiveConfig.iAdapter, (HWND)window_handle,
fullScreenRes, backbuffer_ms_mode, false);
IS_AMD = D3D::IsATIDevice();
fullScreenRes, backbuffer_mm_mode, false);
// Decide framebuffer size
s_backbuffer_width = D3D::GetBackBufferWidth();
s_backbuffer_height = D3D::GetBackBufferHeight();
m_backbuffer_width = D3D::GetBackBufferWidth();
m_backbuffer_height = D3D::GetBackBufferHeight();
m_LastAA = g_ActiveConfig.iMultisamples - 1;
int SupersampleCoeficient = (m_LastAA % 3) + 1;
m_last_efb_scale = g_ActiveConfig.iEFBScale;
m_vsync = g_ActiveConfig.IsVSync();
m_bColorMaskChanged = true;
m_bBlendModeChanged = true;
m_bScissorRectChanged = true;
m_bViewPortChanged = true;
m_bGenerationModeChanged = true;
m_bDepthModeChanged = true;
m_bLogicOpModeChanged = true;
}
void Renderer::Init()
{
m_IS_AMD = D3D::IsATIDevice();
FramebufferManagerBase::SetLastXfbWidth(MAX_XFB_WIDTH);
FramebufferManagerBase::SetLastXfbHeight(MAX_XFB_HEIGHT);
UpdateDrawRectangle();
s_LastAA = g_ActiveConfig.iMultisamples - 1;
int SupersampleCoeficient = (s_LastAA % 3) + 1;
m_LastAA = g_ActiveConfig.iMultisamples - 1;
int SupersampleCoeficient = (m_LastAA % 3) + 1;
s_last_efb_scale = g_ActiveConfig.iEFBScale;
m_last_efb_scale = g_ActiveConfig.iEFBScale;
CalculateTargetSize(SupersampleCoeficient);
PixelShaderManager::SetEfbScaleChanged();
// Make sure to use valid texture sizes
D3D::FixTextureSize(s_target_width, s_target_height);
D3D::FixTextureSize(m_target_width, m_target_height);
// We're not using fixed function.
// Let's just set the matrices to identity to be sure.
@@ -154,8 +160,8 @@ Renderer::Renderer(void *&window_handle)
D3DVIEWPORT9 vp;
vp.X = 0;
vp.Y = 0;
vp.Width = s_backbuffer_width;
vp.Height = s_backbuffer_height;
vp.Width = m_backbuffer_width;
vp.Height = m_backbuffer_height;
vp.MinZ = 0.0f;
vp.MaxZ = 1.0f;
D3D::dev->SetViewport(&vp);
@@ -165,11 +171,11 @@ Renderer::Renderer(void *&window_handle)
D3D::dev->SetDepthStencilSurface(FramebufferManager::GetEFBDepthRTSurface());
vp.X = 0;
vp.Y = 0;
vp.Width = s_target_width;
vp.Height = s_target_height;
vp.Width = m_target_width;
vp.Height = m_target_height;
D3D::dev->SetViewport(&vp);
D3D::dev->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);
D3D::dev->CreateOffscreenPlainSurface(s_backbuffer_width, s_backbuffer_height, D3DFMT_X8R8G8B8, D3DPOOL_SYSTEMMEM, &ScreenShootMEMSurface, NULL);
D3D::dev->CreateOffscreenPlainSurface(m_backbuffer_width, m_backbuffer_height, D3DFMT_X8R8G8B8, D3DPOOL_SYSTEMMEM, &m_screen_shoot_mem_surface, NULL);
D3D::BeginFrame();
// Initial state setup
D3D::SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE);
@@ -181,9 +187,9 @@ Renderer::Renderer(void *&window_handle)
D3D::SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS);
D3D::SetRenderState(D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_ALPHA | D3DCOLORWRITEENABLE_RED | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_BLUE);
D3D::SetRenderState(D3DRS_POINTSCALEENABLE, FALSE);
m_fMaxPointSize = D3D::GetCaps().MaxPointSize;
m_fMax_Point_Size = D3D::GetCaps().MaxPointSize;
// Handle VSync on/off
s_vsync = g_ActiveConfig.IsVSync();
m_vsync = g_ActiveConfig.IsVSync();
m_bColorMaskChanged = true;
m_bBlendModeChanged = true;
m_bScissorRectChanged = true;
@@ -239,37 +245,23 @@ namespace DX9
// With D3D, we have to resize the backbuffer if the window changed
// size.
void Renderer::CheckForResize(bool &resized)
bool Renderer::CheckForResize()
{
RECT rcWindow;
GetClientRect(D3D::hWnd, &rcWindow);
int client_width = rcWindow.right - rcWindow.left;
int client_height = rcWindow.bottom - rcWindow.top;
POINT originPoint = { 0, 0 };
ClientToScreen(D3D::hWnd, &originPoint);
g_renderer->SetWindowRectangle(originPoint.x, originPoint.x + client_width, originPoint.y, originPoint.y + client_height);
// Sanity check
resized = (client_width != Renderer::GetBackbufferWidth()
|| client_height != Renderer::GetBackbufferHeight()
|| s_vsync != g_ActiveConfig.IsVSync()) &&
bool resized = (client_width != g_renderer->GetBackbufferWidth ()
|| client_height != g_renderer->GetBackbufferHeight()
|| m_vsync != g_ActiveConfig.IsVSync()) &&
client_width >= 4 && client_height >= 4;
if (resized)
{
// Handle vsync changes during execution
s_vsync = g_ActiveConfig.IsVSync();
if (!D3D::GetEXSupported())
{
TeardownDeviceObjects();
}
D3D::Reset();
s_backbuffer_width = D3D::GetBackBufferWidth();
s_backbuffer_height = D3D::GetBackBufferHeight();
if (ScreenShootMEMSurface)
ScreenShootMEMSurface->Release();
D3D::dev->CreateOffscreenPlainSurface(Renderer::GetBackbufferWidth(), Renderer::GetBackbufferHeight(),
D3DFMT_X8R8G8B8, D3DPOOL_SYSTEMMEM, &ScreenShootMEMSurface, NULL);
}
return resized;
}
// This function allows the CPU to directly access the EFB.
@@ -449,7 +441,7 @@ void Renderer::ReinterpretPixelData(unsigned int convtype)
// This function has the final picture. We adjust the aspect ratio here.
void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, const EFBRectangle& rc, u64 ticks, float Gamma)
{
if ((!XFBWrited && !g_ActiveConfig.RealXFBEnabled()) || !fbWidth || !fbHeight)
if ((!m_xfb_written && !g_ActiveConfig.RealXFBEnabled()) || !fbWidth || !fbHeight)
{
Core::Callback_VideoCopiedToXFB(false);
return;
@@ -478,27 +470,27 @@ void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, co
int Height = Tr.bottom - Tr.top;
if (X < 0)
{
Width = std::min(Width - X, s_backbuffer_width);
Width = std::min(Width - X, m_backbuffer_width);
X = 0;
}
if (Y < 0)
{
Height = std::min(Height - Y, s_backbuffer_height);
Height = std::min(Height - Y, m_backbuffer_height);
Y = 0;
}
if (Width > s_backbuffer_width)
if (Width > m_backbuffer_width)
{
Width = s_backbuffer_width;
Width = m_backbuffer_width;
}
if (Height > s_backbuffer_height)
if (Height > m_backbuffer_height)
{
Height = s_backbuffer_height;
Height = m_backbuffer_height;
}
if (g_ActiveConfig.iStereoMode)
{
VertexShaderManager::ResetView();
if (s_b3D_RightFrame)
if (m_b3D_RightFrame)
{
if (g_ActiveConfig.iStereoMode == STEREO_SHADER)
{
@@ -506,12 +498,12 @@ void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, co
}
else if (g_ActiveConfig.iStereoMode == STEREO_TAB)
{
Y = (Y / 2) + (s_backbuffer_height / 2);
Y = (Y / 2) + (m_backbuffer_height / 2);
Height = Height / 2;
}
else
{
X = X / 2 + (s_backbuffer_width / 2);
X = X / 2 + (m_backbuffer_width / 2);
Width = Width / 2;
}
VertexShaderManager::TranslateView(-0.001f * g_ActiveConfig.iStereoDepth, 0.0f);
@@ -536,7 +528,7 @@ void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, co
VertexShaderManager::TranslateView(0.001f *g_ActiveConfig.iStereoDepth, 0.0f);
VertexShaderManager::RotateView(0.0001f * g_ActiveConfig.iStereoConvergence, 0.0f);
}
s_b3D_RightFrame = !s_b3D_RightFrame;
m_b3D_RightFrame = !m_b3D_RightFrame;
}
vp.X = X;
@@ -644,16 +636,16 @@ void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, co
{
int source_width = GetTargetRectangle().GetWidth();
int source_height = GetTargetRectangle().GetHeight();
HRESULT hr = D3D::dev->GetRenderTargetData(D3D::GetBackBufferSurface(), ScreenShootMEMSurface);
HRESULT hr = D3D::dev->GetRenderTargetData(D3D::GetBackBufferSurface(), m_screen_shoot_mem_surface);
D3DLOCKED_RECT rect;
if (SUCCEEDED(ScreenShootMEMSurface->LockRect(&rect, GetTargetRectangle().AsRECT(), D3DLOCK_NO_DIRTY_UPDATE | D3DLOCK_NOSYSLOCK | D3DLOCK_READONLY)))
if (SUCCEEDED(m_screen_shoot_mem_surface->LockRect(&rect, GetTargetRectangle().AsRECT(), D3DLOCK_NO_DIRTY_UPDATE | D3DLOCK_NOSYSLOCK | D3DLOCK_READONLY)))
{
AVIDump::Frame state = AVIDump::FetchState(ticks);
DumpFrameData(reinterpret_cast<const u8*>(rect.pBits), source_width, source_height,
rect.Pitch, state, false, true);
FinishFrameData();
ScreenShootMEMSurface->UnlockRect();
m_screen_shoot_mem_surface->UnlockRect();
}
}
@@ -672,8 +664,23 @@ void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, co
SetWindowSize(fbStride, fbHeight);
bool windowResized;
CheckForResize(windowResized);
bool windowResized = CheckForResize();
if (windowResized)
{
// Handle vsync changes during execution
m_vsync = g_ActiveConfig.IsVSync();
if (!D3D::GetEXSupported())
{
TeardownDeviceObjects();
}
D3D::Reset();
m_backbuffer_width = D3D::GetBackBufferWidth();
m_backbuffer_height = D3D::GetBackBufferHeight();
if (m_screen_shoot_mem_surface)
m_screen_shoot_mem_surface->Release();
D3D::dev->CreateOffscreenPlainSurface(m_backbuffer_width, m_backbuffer_height,
D3DFMT_X8R8G8B8, D3DPOOL_SYSTEMMEM, &m_screen_shoot_mem_surface, NULL);
}
bool xfbchanged = false;
@@ -691,16 +698,16 @@ void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, co
if (CalculateTargetSize((newAA % 3) + 1)
|| xfbchanged
|| windowResized
|| s_last_efb_scale != g_ActiveConfig.iEFBScale
|| s_LastAA != newAA)
|| m_last_efb_scale != g_ActiveConfig.iEFBScale
|| m_LastAA != newAA)
{
s_LastAA = newAA;
m_LastAA = newAA;
UpdateDrawRectangle();
int SupersampleCoeficient = (s_LastAA % 3) + 1;
int SupersampleCoeficient = (m_LastAA % 3) + 1;
s_last_efb_scale = g_ActiveConfig.iEFBScale;
m_last_efb_scale = g_ActiveConfig.iEFBScale;
PixelShaderManager::SetEfbScaleChanged();
D3D::dev->SetRenderTarget(0, D3D::GetBackBufferSurface());
D3D::dev->SetDepthStencilSurface(D3D::GetBackBufferDepthSurface());
@@ -718,7 +725,7 @@ void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, co
{
// just resize the frame buffer
g_framebuffer_manager.reset();
g_framebuffer_manager = std::make_unique<FramebufferManager>();
g_framebuffer_manager = std::make_unique<FramebufferManager>(m_target_width, m_target_height);
}
D3D::dev->SetRenderTarget(0, FramebufferManager::GetEFBColorRTSurface());
D3D::dev->SetDepthStencilSurface(FramebufferManager::GetEFBDepthRTSurface());
@@ -903,10 +910,10 @@ void Renderer::RestoreState()
void Renderer::_SetScissorRect()
{
m_bScissorRectChanged = false;
D3D::dev->SetScissorRect(m_ScissorRect.AsRECT());
D3D::dev->SetScissorRect(ConvertEFBRectangle(m_ScissorRect).AsRECT());
}
void Renderer::SetScissorRect(const TargetRectangle& rc)
void Renderer::SetScissorRect(const EFBRectangle& rc)
{
m_ScissorRect = rc;
m_bScissorRectChanged = true;
@@ -948,9 +955,9 @@ void Renderer::_SetBlendMode(bool forceUpdate)
m_bBlendModeChanged = false;
// Our render target always uses an alpha channel, so we need to override the blend functions to assume a destination alpha of 1 if the render target isn't supposed to have an alpha channel
// Example: D3DBLEND_DESTALPHA needs to be D3DBLEND_ONE since the result without an alpha channel is assumed to always be 1.
bool target_has_alpha = bpmem.zcontrol.pixel_format == PEControl::RGBA6_Z24;
bool target_ham_alpha = bpmem.zcontrol.pixel_format == PEControl::RGBA6_Z24;
//really useful for debugging shader and blending errors
bool use_DstAlpha = bpmem.dstalpha.enable && bpmem.blendmode.alphaupdate && target_has_alpha;
bool use_DstAlpha = bpmem.dstalpha.enable && bpmem.blendmode.alphaupdate && target_ham_alpha;
bool use_DualSource = use_DstAlpha && g_ActiveConfig.backend_info.bSupportsDualSourceBlend;
const D3DBLEND d3dSrcFactors[8] =
{
@@ -960,8 +967,8 @@ void Renderer::_SetBlendMode(bool forceUpdate)
D3DBLEND_INVDESTCOLOR,
(use_DualSource) ? D3DBLEND_SRCCOLOR2 : D3DBLEND_SRCALPHA,
(use_DualSource) ? D3DBLEND_INVSRCCOLOR2 : D3DBLEND_INVSRCALPHA,
(target_has_alpha) ? D3DBLEND_DESTALPHA : D3DBLEND_ONE,
(target_has_alpha) ? D3DBLEND_INVDESTALPHA : D3DBLEND_ZERO
(target_ham_alpha) ? D3DBLEND_DESTALPHA : D3DBLEND_ONE,
(target_ham_alpha) ? D3DBLEND_INVDESTALPHA : D3DBLEND_ZERO
};
const D3DBLEND d3dDestFactors[8] =
{
@@ -971,8 +978,8 @@ void Renderer::_SetBlendMode(bool forceUpdate)
D3DBLEND_INVSRCCOLOR,
(use_DualSource) ? D3DBLEND_SRCCOLOR2 : D3DBLEND_SRCALPHA,
(use_DualSource) ? D3DBLEND_INVSRCCOLOR2 : D3DBLEND_INVSRCALPHA,
(target_has_alpha) ? D3DBLEND_DESTALPHA : D3DBLEND_ONE,
(target_has_alpha) ? D3DBLEND_INVDESTALPHA : D3DBLEND_ZERO
(target_ham_alpha) ? D3DBLEND_DESTALPHA : D3DBLEND_ONE,
(target_ham_alpha) ? D3DBLEND_INVDESTALPHA : D3DBLEND_ZERO
};
if (bpmem.blendmode.logicopenable && !bpmem.blendmode.blendenable && !forceUpdate)
@@ -1175,16 +1182,6 @@ void Renderer::_SetLogicOpMode()
}
}
void Renderer::SetDitherMode()
{
// No way to emulate this properly with the defaul pipeline
// and teorically we don't need it because we alway use full color precision.
// To Allow a correct emulation the output of the pixel shaders
// should be reduced to the decired precision and then
// a postproccesing shader should be used to emulate the correct
// dithering matrix and the aproximation equation
}
void Renderer::SetInterlacingMode()
{
// TODO

View File

@@ -11,36 +11,16 @@ namespace DX9
class Renderer : public ::Renderer
{
private:
bool m_bColorMaskChanged;
bool m_bBlendModeChanged;
bool m_bScissorRectChanged;
bool m_bViewPortChanged;
bool m_bViewPortChangedRequested;
TargetRectangle m_ScissorRect;
D3DVIEWPORT9 m_vp;
bool m_bGenerationModeChanged;
bool m_bDepthModeChanged;
bool m_bLogicOpModeChanged;
void _SetColorMask();
void _SetViewport();
void _SetBlendMode(bool forceUpdate);
void _SetScissorRect();
void _SetGenerationMode();
void _SetDepthMode();
void _SetLogicOpMode();
public:
Renderer(void *&window_handle);
~Renderer();
void Init() override;
void SetColorMask();
void SetBlendMode(bool forceUpdate);
void SetScissorRect(const TargetRectangle& rc);
void SetScissorRect(const EFBRectangle& rc);
void SetGenerationMode();
void SetDepthMode();
void SetLogicOpMode();
void SetDitherMode();
void SetSamplerState(int stage, int texindex, bool custom_tex);
void SetInterlacingMode();
void SetViewport();
@@ -70,7 +50,35 @@ public:
void ReinterpretPixelData(unsigned int convtype);
static void CheckForResize(bool &resized);
bool CheckForResize();
private:
bool m_bColorMaskChanged = true;
bool m_bBlendModeChanged = true;
bool m_bScissorRectChanged = true;
bool m_bViewPortChanged = true;
bool m_bViewPortChangedRequested = true;
EFBRectangle m_ScissorRect{};
D3DVIEWPORT9 m_vp{};
bool m_bGenerationModeChanged = true;
bool m_bDepthModeChanged = true;
bool m_bLogicOpModeChanged = true;
u32 m_blendMode = 0;
u32 m_LastAA = 0;
bool m_IS_AMD = false;
float m_fMax_Point_Size = 0;
bool m_vsync = false;
bool m_b3D_RightFrame = false;
bool m_last_fullscreen_mode = false;
void _SetColorMask();
void _SetViewport();
void _SetBlendMode(bool forceUpdate);
void _SetScissorRect();
void _SetGenerationMode();
void _SetDepthMode();
void _SetLogicOpMode();
void SetupDeviceObjects();
void TeardownDeviceObjects();
};
} // namespace DX9

View File

@@ -82,7 +82,6 @@ static u32 s_memPoolTextureW[MEM_TEXTURE_POOL_SIZE];
static u32 s_memPoolTextureH[MEM_TEXTURE_POOL_SIZE];
static std::unique_ptr<Depalettizer> s_depaletizer;
static std::unique_ptr<TextureScaler> s_scaler;
TextureCache::TCacheEntry::~TCacheEntry()
{
@@ -194,38 +193,6 @@ void TextureCache::TCacheEntry::Load(const u8* src, u32 width, u32 height,
ReplaceTexture(src, width, height, expanded_width, level, swap_r_b);
}
void TextureCache::TCacheEntry::Load(const u8* src, u32 width, u32 height, u32 expandedWidth,
u32 expandedHeight, const s32 texformat, const u32 tlutaddr, const TlutFormat tlutfmt, u32 level)
{
bool swap_r_b = PC_TEX_FMT_RGBA32 == config.pcformat;
u8* data = g_texture_cache->GetTemporalBuffer();
TexDecoder_Decode(data, src, expandedWidth, expandedHeight, texformat, tlutaddr, tlutfmt, swap_r_b, compressed);
if (is_scaled)
{
swap_r_b = true;
data = (u8*)s_scaler->Scale((u32*)data, expandedWidth, height);
width *= g_ActiveConfig.iTexScalingFactor;
height *= g_ActiveConfig.iTexScalingFactor;
expandedWidth *= g_ActiveConfig.iTexScalingFactor;
}
ReplaceTexture(data, width, height, expandedWidth, level, swap_r_b);
}
void TextureCache::TCacheEntry::LoadFromTmem(const u8* ar_src, const u8* gb_src, u32 width, u32 height,
u32 expanded_width, u32 expanded_Height, u32 level)
{
u8* data = g_texture_cache->GetTemporalBuffer();
TexDecoder_DecodeBGRA8FromTmem((u32*)data, ar_src, gb_src, expanded_width, expanded_Height);
if (is_scaled)
{
data = (u8*)s_scaler->Scale((u32*)data, expanded_width, height);
width *= g_ActiveConfig.iTexScalingFactor;
height *= g_ActiveConfig.iTexScalingFactor;
expanded_width *= g_ActiveConfig.iTexScalingFactor;
}
ReplaceTexture(data, width, height, expanded_width, level, false);
}
void TextureCache::TCacheEntry::FromRenderTarget(bool is_depth_copy, const EFBRectangle& srcRect,
bool scaleByHalf, unsigned int cbufid, const float *colmat, u32 width, u32 height)
{
@@ -288,7 +255,7 @@ void TextureCache::TCacheEntry::FromRenderTarget(bool is_depth_copy, const EFBRe
s32 SSAAMode = g_ActiveConfig.iMultisamples - 1;
D3D::drawShadedTexQuad(read_texture, &sourcerect,
Renderer::GetTargetWidth(), Renderer::GetTargetHeight(),
g_renderer->GetTargetWidth(), g_renderer->GetTargetHeight(),
config.width, config.height,
PixelShaderCache::GetDepthMatrixProgram(SSAAMode, is_depth_copy && bformat != FOURCC_RAWZ),
VertexShaderCache::GetSimpleVertexShader(SSAAMode));
@@ -304,21 +271,12 @@ void TextureCache::TCacheEntry::FromRenderTarget(bool is_depth_copy, const EFBRe
g_renderer->RestoreAPIState();
}
void TextureCache::CopyEFB(u8* dst, u32 format, u32 native_width, u32 bytes_per_row, u32 num_blocks_y, u32 memory_stride,
bool is_depth_copy, const EFBRectangle& srcRect,
bool isIntensity, bool scaleByHalf)
void TextureCache::CopyEFB(u8* dst, const EFBCopyFormat& format, u32 native_width, u32 bytes_per_row,
u32 num_blocks_y, u32 memory_stride, bool is_depth_copy,
const EFBRectangle& src_rect, bool scale_by_half)
{
TextureConverter::EncodeToRamFromTexture(
dst,
format,
native_width,
bytes_per_row,
num_blocks_y,
memory_stride,
is_depth_copy,
isIntensity,
scaleByHalf,
srcRect);
TextureConverter::EncodeToRamFromTexture(dst, format, native_width, bytes_per_row, num_blocks_y,
memory_stride, is_depth_copy, src_rect, scale_by_half);
}
bool TextureCache::Palettize(TCacheEntryBase* entry, const TCacheEntryBase* base_entry)
@@ -378,7 +336,6 @@ TextureCache::TextureCache()
s_memPoolTextureH[i] = 1024u;
}
s_depaletizer = std::make_unique<Depalettizer>();
s_scaler = std::make_unique<TextureScaler>();
}
TextureCache::~TextureCache()
@@ -392,7 +349,6 @@ TextureCache::~TextureCache()
}
}
s_depaletizer.reset();
s_scaler.reset();
}
}

View File

@@ -41,13 +41,6 @@ private:
void Load(const u8* src, u32 width, u32 height,
u32 expanded_width, u32 level) override;
void LoadMaterialMap(const u8* src, u32 width, u32 height, u32 level) override
{};
void Load(const u8* src, u32 width, u32 height, u32 expandedWidth,
u32 expandedHeight, const s32 texformat, const u32 tlutaddr, const TlutFormat tlutfmt, u32 level) override;
void LoadFromTmem(const u8* ar_src, const u8* gb_src, u32 width, u32 height,
u32 expanded_width, u32 expanded_Height, u32 level) override;
void FromRenderTarget(bool is_depth_copy, const EFBRectangle& srcRect,
bool scaleByHalf, unsigned int cbufid, const float *colmat, u32 width, u32 height) override;
bool SupportsMaterialMap() const override
@@ -66,9 +59,9 @@ private:
TCacheEntryBase* CreateTexture(const TCacheEntryConfig& config);
void CopyEFB(u8* dst, u32 format, u32 native_width, u32 bytes_per_row, u32 num_blocks_y, u32 memory_stride,
bool is_depth_copy, const EFBRectangle& srcRect,
bool isIntensity, bool scaleByHalf) override;
void CopyEFB(u8* dst, const EFBCopyFormat& format, u32 native_width, u32 bytes_per_row,
u32 num_blocks_y, u32 memory_stride, bool is_depth_copy,
const EFBRectangle& src_rect, bool scale_by_half) override;
bool Palettize(TCacheEntryBase* entry, const TCacheEntryBase* base_entry) override;
void LoadLut(u32 lutFmt, void* addr, u32 size);
bool CompileShaders() override

View File

@@ -101,10 +101,12 @@ static u32 xfreadBuffers = 0;
static LPDIRECT3DPIXELSHADER9 s_rgbToYuyvProgram = nullptr;
static LPDIRECT3DPIXELSHADER9 s_yuyvToRgbProgram = nullptr;
// Not all slots are taken - but who cares.
const u32 NUM_ENCODING_PROGRAMS = 64;
static LPDIRECT3DPIXELSHADER9 s_encodingPrograms[NUM_ENCODING_PROGRAMS];
static bool s_encodingProgramsFailed[NUM_ENCODING_PROGRAMS];
struct EncodingProgram
{
LPDIRECT3DPIXELSHADER9 program;
bool failed;
};
static std::map<EFBCopyFormat, EncodingProgram> s_encoding_programs;
void CreateRgbToYuyvProgram()
{
@@ -169,43 +171,38 @@ void CreateYuyvToRgbProgram()
delete[] FProgram;
}
LPDIRECT3DPIXELSHADER9 GetOrCreateEncodingShader(u32 format)
LPDIRECT3DPIXELSHADER9 GetOrCreateEncodingShader(const EFBCopyFormat& format)
{
if (format > NUM_ENCODING_PROGRAMS)
auto iter = s_encoding_programs.find(format);
if (iter != s_encoding_programs.end() && !iter->second.failed)
return iter->second.program;
if (iter->second.failed)
{
PanicAlert("Unknown texture copy format: 0x%x\n", format);
return s_encodingPrograms[0];
return nullptr;
}
if (!s_encodingPrograms[format])
{
if (s_encodingProgramsFailed[format])
{
// we already failed to create a shader for this format,
// so instead of re-trying and showing the same error message every frame, just return.
return nullptr;
}
const char* shader = TextureConversionShaderLegacy::GenerateEncodingShader(format);
const char* shader = TextureConversionShaderLegacy::GenerateEncodingShader(format);
#if defined(_DEBUG) || defined(DEBUGFAST)
if (g_ActiveConfig.iLog & CONF_SAVESHADERS && shader)
{
static int counter = 0;
char szTemp[MAX_PATH];
sprintf(szTemp, "%senc_%04i.txt", File::GetUserPath(D_DUMP_IDX).c_str(), counter++);
if (g_ActiveConfig.iLog & CONF_SAVESHADERS && shader)
{
static int counter = 0;
char szTemp[MAX_PATH];
sprintf(szTemp, "%senc_%04i.txt", File::GetUserPath(D_DUMP_IDX).c_str(), counter++);
SaveData(szTemp, shader);
}
#endif
s_encodingPrograms[format] = D3D::CompileAndCreatePixelShader(shader, (int)strlen(shader));
if (!s_encodingPrograms[format])
{
ERROR_LOG(VIDEO, "Failed to create encoding fragment program");
s_encodingProgramsFailed[format] = true;
}
SaveData(szTemp, shader);
}
return s_encodingPrograms[format];
#endif
EncodingProgram program;
program.program = D3D::CompileAndCreatePixelShader(shader, (int)strlen(shader));
program.failed = !program.program;
if (program.failed)
{
ERROR_LOG(VIDEO, "Failed to create encoding fragment program");
}
return s_encoding_programs.emplace(format, program).first->second.program;
}
void Init()
@@ -214,11 +211,6 @@ void Init()
CreateYuyvToRgbProgram();
xfreadBuffers = 0;
WorkingBuffers = 0;
for (unsigned int i = 0; i < NUM_ENCODING_PROGRAMS; i++)
{
s_encodingPrograms[i] = nullptr;
s_encodingProgramsFailed[i] = false;
}
for (unsigned int i = 0; i < NUM_TRANSFORM_BUFFERS; i++)
{
TrnBuffers[i].Clear();
@@ -238,12 +230,13 @@ void Shutdown()
s_yuyvToRgbProgram->Release();
s_yuyvToRgbProgram = nullptr;
for (unsigned int i = 0; i < NUM_ENCODING_PROGRAMS; i++)
for (auto& program : s_encoding_programs)
{
if (s_encodingPrograms[i])
s_encodingPrograms[i]->Release();
s_encodingPrograms[i] = nullptr;
if(program.second.program)
program.second.program->Release();
}
s_encoding_programs.clear();
for (unsigned int i = 0; i < NUM_TRANSFORM_BUFFERS; i++)
{
TrnBuffers[i].Release();
@@ -366,8 +359,9 @@ void EncodeToRamUsingShader(LPDIRECT3DPIXELSHADER9 shader, LPDIRECT3DTEXTURE9 sr
hr = s_texConvReadSurface->UnlockRect();
}
// returns size of the encoded data (in bytes)
void EncodeToRamFromTexture(u8* dest_ptr, u32 format, u32 native_width, u32 bytes_per_row, u32 num_blocks_y, u32 memory_stride,
bool is_depth_copy, bool bIsIntensityFmt, bool bScaleByHalf, const EFBRectangle& source)
void EncodeToRamFromTexture(u8* dest_ptr, const EFBCopyFormat& format, u32 native_width,
u32 bytes_per_row, u32 num_blocks_y, u32 memory_stride,
bool is_depth_copy, const EFBRectangle& src_rect, bool scale_by_half)
{
LPDIRECT3DPIXELSHADER9 texconv_shader = GetOrCreateEncodingShader(format);
if (!texconv_shader)
@@ -376,25 +370,25 @@ void EncodeToRamFromTexture(u8* dest_ptr, u32 format, u32 native_width, u32 byte
FramebufferManager::GetEFBDepthTexture() :
FramebufferManager::GetEFBColorTexture();
const u16 blkW = TexDecoder_GetBlockWidthInTexels(format);
const u16 blkH = TexDecoder_GetBlockHeightInTexels(format);
const u16 samples = TextureConversionShader::GetEncodedSampleCount(format);
const u16 blkW = TexDecoder_GetBlockWidthInTexels(format.copy_format);
const u16 blkH = TexDecoder_GetBlockHeightInTexels(format.copy_format);
const u16 samples = TextureConversionShader::GetEncodedSampleCount(format.copy_format);
// only copy on cache line boundaries
// extra pixels are copied but not displayed in the resulting texture
s32 expandedWidth = static_cast<s32>(Common::AlignUpSizePow2(native_width, blkW));
s32 expandedHeight = num_blocks_y * blkH;
float sampleStride = bScaleByHalf ? 2.f : 1.f;
float sampleStride = scale_by_half ? 2.f : 1.f;
TextureConversionShaderLegacy::SetShaderParameters(
(float)expandedWidth,
(float)Renderer::EFBToScaledY(expandedHeight), // TODO: Why do we scale this?
(float)Renderer::EFBToScaledX(source.left),
(float)Renderer::EFBToScaledY(source.top),
Renderer::EFBToScaledXf(sampleStride),
Renderer::EFBToScaledYf(sampleStride),
(float)Renderer::GetTargetWidth(),
(float)Renderer::GetTargetHeight());
(float)g_renderer->EFBToScaledY(expandedHeight), // TODO: Why do we scale this?
(float)g_renderer->EFBToScaledX(src_rect.left),
(float)g_renderer->EFBToScaledY(src_rect.top),
g_renderer->EFBToScaledXf(sampleStride),
g_renderer->EFBToScaledYf(sampleStride),
(float)g_renderer->GetTargetWidth(),
(float)g_renderer->GetTargetHeight());
D3D::dev->SetPixelShaderConstantF(C_COLORMATRIX, PixelShaderManager::GetBuffer(), 2);
TargetRectangle scaledSource;
scaledSource.top = 0;
@@ -405,7 +399,7 @@ void EncodeToRamFromTexture(u8* dest_ptr, u32 format, u32 native_width, u32 byte
texconv_shader,
read_texture,
scaledSource,
dest_ptr, scaledSource.right * 4, expandedHeight, memory_stride, bytes_per_row, bScaleByHalf, 1.0f);
dest_ptr, scaledSource.right * 4, expandedHeight, memory_stride, bytes_per_row, scale_by_half, 1.0f);
}
void EncodeToRamYUYV(LPDIRECT3DTEXTURE9 srcTexture, const TargetRectangle& sourceRc, u8* destAddr, u32 dstwidth, u32 dstStride, u32 dstHeight, float Gamma)
@@ -417,8 +411,8 @@ void EncodeToRamYUYV(LPDIRECT3DTEXTURE9 srcTexture, const TargetRectangle& sourc
0.0f,
1.0f,
1.0f,
(float)Renderer::GetTargetWidth(),
(float)Renderer::GetTargetHeight());
(float)g_renderer->GetTargetWidth(),
(float)g_renderer->GetTargetHeight());
D3D::dev->SetPixelShaderConstantF(C_COLORMATRIX, PixelShaderManager::GetBuffer(), 2);
g_renderer->ResetAPIState();
EncodeToRamUsingShader(s_rgbToYuyvProgram, srcTexture, sourceRc, destAddr,

View File

@@ -28,8 +28,9 @@ void EncodeToRamYUYV(LPDIRECT3DTEXTURE9 srcTexture, const TargetRectangle& sourc
void DecodeToTexture(u32 xfbAddr, int srcWidth, int srcHeight, LPDIRECT3DTEXTURE9 destTexture);
// returns size of the encoded data (in bytes)
void EncodeToRamFromTexture(u8* dest_ptr, u32 format, u32 native_width, u32 bytes_per_row, u32 num_blocks_y, u32 memory_stride,
bool is_depth_copy, bool bIsIntensityFmt, bool bScaleByHalf, const EFBRectangle& source);
void EncodeToRamFromTexture(u8* dest_ptr, const EFBCopyFormat& format, u32 native_width,
u32 bytes_per_row, u32 num_blocks_y, u32 memory_stride,
bool is_depth_copy, const EFBRectangle& src_rect, bool scale_by_half);
}

View File

@@ -192,8 +192,8 @@ VertexManager::VertexManager()
{
LocalVBuffer.resize(MAXVBUFFERSIZE);
s_pCurBufferPointer = s_pBaseBufferPointer = &LocalVBuffer[0];
s_pEndBufferPointer = s_pBaseBufferPointer + LocalVBuffer.size();
m_pCurBufferPointer = m_pBaseBufferPointer = &LocalVBuffer[0];
m_pEndBufferPointer = m_pBaseBufferPointer + LocalVBuffer.size();
LocalIBuffer.resize(MAXIBUFFERSIZE);
}
@@ -240,13 +240,13 @@ void VertexManager::PrepareDrawBuffers(u32 stride)
DestroyDeviceObjects();
return;
}
memcpy(p_vertices_base, s_pBaseBufferPointer, data_size);
memcpy(p_vertices_base, m_pBaseBufferPointer, data_size);
p_vertices = p_vertices_base + data_size;
if (current_primitive_type == PRIMITIVE_TRIANGLES)
if (m_current_primitive_type == PRIMITIVE_TRIANGLES)
{
memcpy(p_indices, indices, m_index_len * sizeof(u16));
}
else if (current_primitive_type == PRIMITIVE_LINES)
else if (m_current_primitive_type == PRIMITIVE_LINES)
{
for (u32 i = 0; i < (m_index_len - 1); i += 2)
{
@@ -256,12 +256,12 @@ void VertexManager::PrepareDrawBuffers(u32 stride)
// Get the position in the stream o f the first vertex
u32 currentstride = first_index * stride;
// Get The first vertex Position data
Float_2* base_vertex_0 = (Float_2*)(s_pBaseBufferPointer + currentstride);
Float_2* base_vertex_0 = (Float_2*)(m_pBaseBufferPointer + currentstride);
// Get The blendindices data
U8_4* blendindices_vertex_0 = (U8_4*)(p_vertices_base + currentstride + stride - sizeof(U8_4));
// Get The first vertex Position data
currentstride = second_index * stride;
Float_2* base_vertex_1 = (Float_2*)(s_pBaseBufferPointer + currentstride);
Float_2* base_vertex_1 = (Float_2*)(m_pBaseBufferPointer + currentstride);
U8_4* blendindices_vertex_1 = (U8_4*)(p_vertices_base + currentstride + stride - sizeof(U8_4));
// Calculate line orientation
@@ -327,7 +327,7 @@ void VertexManager::PrepareDrawBuffers(u32 stride)
p_indices++;
}
}
else if (current_primitive_type == PRIMITIVE_POINTS)
else if (m_current_primitive_type == PRIMITIVE_POINTS)
{
for (u32 i = 0; i < m_index_len; i++)
{
@@ -336,7 +336,7 @@ void VertexManager::PrepareDrawBuffers(u32 stride)
// Calculate stream Position
int currentstride = pointindex * stride;
// Get data Pointer for vertex replication
u8* base_vertex = s_pBaseBufferPointer + currentstride;
u8* base_vertex = m_pBaseBufferPointer + currentstride;
U8_4* blendindices_vertex_0 = (U8_4*)(p_vertices_base + currentstride + stride - sizeof(U8_4));
// Generate Extra vertices
@@ -488,7 +488,7 @@ void VertexManager::vFlush(bool useDstAlpha)
m_total_index_len = m_index_len;
NativeVertexFormat* current_vertex_format = VertexLoaderManager::GetCurrentVertexFormat();
const u32 stride = current_vertex_format->GetVertexStride();
switch (current_primitive_type)
switch (m_current_primitive_type)
{
case PRIMITIVE_POINTS:
// We need point emulation so setup values to allow point to triangle translation
@@ -522,7 +522,7 @@ void VertexManager::vFlush(bool useDstAlpha)
goto shader_fail;
}
g_renderer->ApplyState(false);
if (current_primitive_type != PRIMITIVE_TRIANGLES)
if (m_current_primitive_type != PRIMITIVE_TRIANGLES)
{
// if we use emulation setup the offsets for the vertex shaders
SetPLRasterOffsets();
@@ -584,7 +584,7 @@ void VertexManager::vFlush(bool useDstAlpha)
Draw(stride);
g_renderer->RestoreState();
}
if (current_primitive_type != PRIMITIVE_TRIANGLES)
if (m_current_primitive_type != PRIMITIVE_TRIANGLES)
{
D3D::RefreshRenderState(D3DRS_CULLMODE);
}
@@ -595,7 +595,7 @@ shader_fail:
void VertexManager::ResetBuffer(u32 stride)
{
s_pCurBufferPointer = s_pBaseBufferPointer;
m_pCurBufferPointer = m_pBaseBufferPointer;
IndexGenerator::Start(GetIndexBuffer());
}

View File

@@ -93,7 +93,7 @@ void VideoBackend::InitBackendInfo()
g_Config.backend_info.bSupportsClipControl = true;
g_Config.backend_info.bSupportsSSAA = false;
g_Config.backend_info.bSupportsTessellation = false;
g_Config.backend_info.bSupportsComputeTextureDecoding = false;
g_Config.backend_info.bSupportsGPUTextureDecoding = false;
g_Config.backend_info.bSupportsComputeTextureEncoding = false;
g_Config.backend_info.bSupportsDepthClamp = false;
g_Config.backend_info.bSupportsMultithreading = false;
@@ -146,6 +146,7 @@ void VideoBackend::Video_Prepare()
g_vertex_manager = std::make_unique<VertexManager>();
g_perf_query = std::make_unique<PerfQuery>();
g_renderer = std::make_unique<Renderer>(m_window_handle);
g_renderer->Init();
UpdateActiveConfig();
}

View File

@@ -110,7 +110,7 @@ FramebufferManager::FramebufferManager(int targetWidth, int targetHeight, int ms
{
m_textureType = GL_TEXTURE_2D_MULTISAMPLE_ARRAY;
if (g_ogl_config.bSupports3DTextureStorage)
if (g_ogl_config.bSupports3DTextureStorageMultisample)
{
glBindTexture(m_textureType, m_efbColor);
glTexStorage3DMultisample(m_textureType, m_msaaSamples, GL_RGBA8, m_targetWidth, m_targetHeight, m_EFBLayers, false);
@@ -140,7 +140,7 @@ FramebufferManager::FramebufferManager(int targetWidth, int targetHeight, int ms
{
m_textureType = GL_TEXTURE_2D_MULTISAMPLE;
if (g_ogl_config.bSupports2DTextureStorage)
if (g_ogl_config.bSupports2DTextureStorageMultisample)
{
glBindTexture(m_textureType, m_efbColor);
glTexStorage2DMultisample(m_textureType, m_msaaSamples, GL_RGBA8, m_targetWidth, m_targetHeight, false);

View File

@@ -0,0 +1,105 @@
// Copyright 2016 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#pragma once
#include "Common/GL/GLExtensions/GLExtensions.h"
#ifndef GL_TIME_ELAPSED
#define GL_TIME_ELAPSED 0x88BF
#endif
namespace OGL
{
/*
* This class can be used to measure the time it takes for the GPU to perform a draw call
* or compute dispatch. To use:
*
* - Create an instance of GPUTimer before issuing the draw call.
* (this can be before or after any binding that needs to be done)
*
* - (optionally) call Begin(). This is not needed for a single draw call.
*
* - Issue the draw call or compute dispatch as normal.
*
* - (optionally) call End(). This is not necessary for a single draw call.
*
* - Call GetTime{Seconds,Milliseconds,Nanoseconds} to determine how long the operation
* took to execute on the GPU.
*
* NOTE: When the timer is read back, this will force a GL flush, so the more often a timer is used,
* the larger of a performance impact it will have. Only one timer can be active at any time, due to
* using GL_TIME_ELAPSED. This is not enforced by the class, however.
*
*/
class GPUTimer final
{
public:
GPUTimer()
{
glGenQueries(1, &m_query_id);
Begin();
}
~GPUTimer()
{
End();
glDeleteQueries(1, &m_query_id);
}
void Begin()
{
if (m_started)
glEndQuery(GL_TIME_ELAPSED);
glBeginQuery(GL_TIME_ELAPSED, m_query_id);
m_started = true;
}
void End()
{
if (!m_started)
return;
glEndQuery(GL_TIME_ELAPSED);
m_started = false;
}
double GetTimeSeconds()
{
GetResult();
return static_cast<double>(m_result) / 1000000000.0;
}
double GetTimeMilliseconds()
{
GetResult();
return static_cast<double>(m_result) / 1000000.0;
}
u32 GetTimeNanoseconds()
{
GetResult();
return m_result;
}
private:
void GetResult()
{
if (m_has_result)
return;
if (m_started)
End();
glGetQueryObjectuiv(m_query_id, GL_QUERY_RESULT, &m_result);
m_has_result = true;
}
GLuint m_query_id;
GLuint m_result = 0;
bool m_started = false;
bool m_has_result = false;
};
} // namespace OGL

View File

@@ -53,6 +53,7 @@
<ItemGroup>
<ClInclude Include="BoundingBox.h" />
<ClInclude Include="FramebufferManager.h" />
<ClInclude Include="GPUTimer.h" />
<ClInclude Include="PerfQuery.h" />
<ClInclude Include="PostProcessing.h" />
<ClInclude Include="ProgramShaderCache.h" />

View File

@@ -90,6 +90,9 @@
<ClInclude Include="BoundingBox.h">
<Filter>Render</Filter>
</ClInclude>
<ClInclude Include="GPUTimer.h">
<Filter>GLUtil</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<Text Include="CMakeLists.txt" />

View File

@@ -64,6 +64,8 @@ static std::string GetGLSLVersionString()
return "#version 330";
case GLSL_400:
return "#version 400";
case GLSL_430:
return "#version 430";
default:
// Shouldn't ever hit this
return "#version ERROR";
@@ -106,28 +108,30 @@ void SHADER::SetProgramVariables()
}
}
void SHADER::SetProgramBindings()
void SHADER::SetProgramBindings(bool is_compute)
{
if (g_ActiveConfig.backend_info.bSupportsDualSourceBlend)
if (!is_compute)
{
// So we do support extended blending
// So we need to set a few more things here.
// Bind our out locations
glBindFragDataLocationIndexed(glprogid, 0, 0, "ocol0");
glBindFragDataLocationIndexed(glprogid, 0, 1, "ocol1");
if (g_ActiveConfig.backend_info.bSupportsDualSourceBlend)
{
// So we do support extended blending
// So we need to set a few more things here.
// Bind our out locations
glBindFragDataLocationIndexed(glprogid, 0, 0, "ocol0");
glBindFragDataLocationIndexed(glprogid, 0, 1, "ocol1");
}
// Need to set some attribute locations
glBindAttribLocation(glprogid, SHADER_POSITION_ATTRIB, "rawpos");
glBindAttribLocation(glprogid, SHADER_POSMTX_ATTRIB, "fposmtx");
glBindAttribLocation(glprogid, SHADER_COLOR0_ATTRIB, "color0");
glBindAttribLocation(glprogid, SHADER_COLOR1_ATTRIB, "color1");
glBindAttribLocation(glprogid, SHADER_NORM0_ATTRIB, "rawnorm0");
glBindAttribLocation(glprogid, SHADER_NORM1_ATTRIB, "rawnorm1");
glBindAttribLocation(glprogid, SHADER_NORM2_ATTRIB, "rawnorm2");
}
// Need to set some attribute locations
glBindAttribLocation(glprogid, SHADER_POSITION_ATTRIB, "rawpos");
glBindAttribLocation(glprogid, SHADER_POSMTX_ATTRIB, "fposmtx");
glBindAttribLocation(glprogid, SHADER_COLOR0_ATTRIB, "color0");
glBindAttribLocation(glprogid, SHADER_COLOR1_ATTRIB, "color1");
glBindAttribLocation(glprogid, SHADER_NORM0_ATTRIB, "rawnorm0");
glBindAttribLocation(glprogid, SHADER_NORM1_ATTRIB, "rawnorm1");
glBindAttribLocation(glprogid, SHADER_NORM2_ATTRIB, "rawnorm2");
for (int i = 0; i < 8; i++)
{
char attrib_name[8];
@@ -311,7 +315,7 @@ bool ProgramShaderCache::CompileShader(SHADER& shader, const char* vcode, const
if (g_ogl_config.bSupportsGLSLCache)
glProgramParameteri(pid, GL_PROGRAM_BINARY_RETRIEVABLE_HINT, GL_TRUE);
shader.SetProgramBindings();
shader.SetProgramBindings(false);
glLinkProgram(pid);
@@ -326,10 +330,10 @@ bool ProgramShaderCache::CompileShader(SHADER& shader, const char* vcode, const
glGetProgramiv(pid, GL_INFO_LOG_LENGTH, &length);
if (linkStatus != GL_TRUE || (length > 1 && DEBUG_GLSL))
{
GLsizei charsWritten;
GLchar* infoLog = new GLchar[length];
glGetProgramInfoLog(pid, length, &charsWritten, infoLog);
ERROR_LOG(VIDEO, "Program info log:\n%s", infoLog);
std::string info_log;
info_log.resize(length);
glGetProgramInfoLog(pid, length, &length, &info_log[0]);
ERROR_LOG(VIDEO, "Program info log:\n%s", info_log.c_str());
std::string filename = StringFromFormat("%sbad_p_%d.txt", File::GetUserPath(D_DUMP_IDX).c_str(), num_failures++);
std::ofstream file;
@@ -337,7 +341,7 @@ bool ProgramShaderCache::CompileShader(SHADER& shader, const char* vcode, const
file << s_glsl_header << vcode << s_glsl_header << pcode;
if (gcode)
file << s_glsl_header << gcode;
file << infoLog;
file << info_log;
file.close();
if (linkStatus != GL_TRUE)
@@ -345,10 +349,8 @@ bool ProgramShaderCache::CompileShader(SHADER& shader, const char* vcode, const
PanicAlert("Failed to link shaders: %s\n"
"Debug info (%s, %s, %s):\n%s",
filename.c_str(),
g_ogl_config.gl_vendor, g_ogl_config.gl_renderer, g_ogl_config.gl_version, infoLog);
g_ogl_config.gl_vendor, g_ogl_config.gl_renderer, g_ogl_config.gl_version, info_log.c_str());
}
delete[] infoLog;
}
if (linkStatus != GL_TRUE)
{
@@ -365,6 +367,73 @@ bool ProgramShaderCache::CompileShader(SHADER& shader, const char* vcode, const
return true;
}
bool ProgramShaderCache::CompileComputeShader(SHADER& shader, const std::string& code)
{
// We need to enable GL_ARB_compute_shader for drivers that support the extension,
// but not GLSL 4.3. Mesa is one example.
std::string header;
if (g_ActiveConfig.backend_info.bSupportsComputeShaders &&
g_ogl_config.eSupportedGLSLVersion < GLSL_430)
{
header = "#extension GL_ARB_compute_shader : enable\n";
}
GLuint shader_id = CompileSingleShader(GL_COMPUTE_SHADER, (header + code).c_str());
if (!shader_id)
return false;
GLuint pid = shader.glprogid = glCreateProgram();
glAttachShader(pid, shader_id);
if (g_ogl_config.bSupportsGLSLCache)
glProgramParameteri(pid, GL_PROGRAM_BINARY_RETRIEVABLE_HINT, GL_TRUE);
shader.SetProgramBindings(true);
glLinkProgram(pid);
// original shaders aren't needed any more
glDeleteShader(shader_id);
GLint linkStatus;
glGetProgramiv(pid, GL_LINK_STATUS, &linkStatus);
GLsizei length = 0;
glGetProgramiv(pid, GL_INFO_LOG_LENGTH, &length);
if (linkStatus != GL_TRUE || (length > 1 && DEBUG_GLSL))
{
std::string info_log;
info_log.resize(length);
glGetProgramInfoLog(pid, length, &length, &info_log[0]);
ERROR_LOG(VIDEO, "Program info log:\n%s", info_log.c_str());
std::string filename =
StringFromFormat("%sbad_p_%d.txt", File::GetUserPath(D_DUMP_IDX).c_str(), num_failures++);
std::ofstream file;
OpenFStream(file, filename, std::ios_base::out);
file << s_glsl_header << code;
file << info_log;
file.close();
if (linkStatus != GL_TRUE)
{
PanicAlert("Failed to link shaders: %s\n"
"Debug info (%s, %s, %s):\n%s",
filename.c_str(), g_ogl_config.gl_vendor, g_ogl_config.gl_renderer,
g_ogl_config.gl_version, info_log.c_str());
}
}
if (linkStatus != GL_TRUE)
{
// Compile failed
ERROR_LOG(VIDEO, "Program linking failed; see info log");
// Don't try to use this shader
glDeleteProgram(pid);
return false;
}
return true;
}
GLuint ProgramShaderCache::CompileSingleShader(GLuint type, const char* code, const char **macros,
const u32 count)
{
@@ -385,30 +454,45 @@ GLuint ProgramShaderCache::CompileSingleShader(GLuint type, const char* code, co
if (compileStatus != GL_TRUE || (length > 1 && DEBUG_GLSL))
{
GLsizei charsWritten;
GLchar* infoLog = new GLchar[length];
glGetShaderInfoLog(result, length, &charsWritten, infoLog);
ERROR_LOG(VIDEO, "%s Shader info log:\n%s", type == GL_VERTEX_SHADER ? "VS" : type == GL_FRAGMENT_SHADER ? "PS" : "GS", infoLog);
std::string info_log;
info_log.resize(length);
glGetShaderInfoLog(result, length, &length, &info_log[0]);
const char* prefix = "";
switch (type)
{
case GL_VERTEX_SHADER:
prefix = "vs";
break;
case GL_GEOMETRY_SHADER:
prefix = "gs";
break;
case GL_FRAGMENT_SHADER:
prefix = "ps";
break;
case GL_COMPUTE_SHADER:
prefix = "cs";
break;
}
ERROR_LOG(VIDEO, "%s Shader info log:\n%s", prefix, info_log.c_str());
std::string filename = StringFromFormat("%sbad_%s_%04i.txt",
File::GetUserPath(D_DUMP_IDX).c_str(),
type == GL_VERTEX_SHADER ? "vs" : type == GL_FRAGMENT_SHADER ? "ps" : "gs",
prefix,
num_failures++);
std::ofstream file;
OpenFStream(file, filename, std::ios_base::out);
file << s_glsl_header << code << infoLog;
file << s_glsl_header << code << info_log;
file.close();
if (compileStatus != GL_TRUE)
{
PanicAlert("Failed to compile %s shader: %s\n"
"Debug info (%s, %s, %s):\n%s",
type == GL_VERTEX_SHADER ? "vertex" : type == GL_FRAGMENT_SHADER ? "pixel" : "geometry",
filename.c_str(),
g_ogl_config.gl_vendor, g_ogl_config.gl_renderer, g_ogl_config.gl_version, infoLog);
prefix, filename.c_str(), g_ogl_config.gl_vendor, g_ogl_config.gl_renderer,
g_ogl_config.gl_version, info_log.c_str());
}
delete[] infoLog;
}
if (compileStatus != GL_TRUE)
{
@@ -450,12 +534,12 @@ void ProgramShaderCache::Init()
s_buffer = StreamBuffer::Create(GL_UNIFORM_BUFFER, s_ubo_buffer_size * 2048);
pKey_t gameid = (pKey_t)GetMurmurHash3(reinterpret_cast<const u8*>(SConfig::GetInstance().m_strGameID.data()), (u32)SConfig::GetInstance().m_strGameID.size(), 0);
pKey_t gameid = (pKey_t)GetMurmurHash3(reinterpret_cast<const u8*>(SConfig::GetInstance().GetGameID().data()), (u32)SConfig::GetInstance().GetGameID().size(), 0);
pshaders = PCache::Create(
gameid,
PIXELSHADERGEN_UID_VERSION * VERTEXSHADERGEN_UID_VERSION * GEOMETRYSHADERGEN_UID_VERSION,
"Ishiiruka.ps.OGL",
StringFromFormat("%s.ps.OGL", SConfig::GetInstance().m_strGameID.c_str())
StringFromFormat("%s.ps.OGL", SConfig::GetInstance().GetGameID().c_str())
);
// Read our shader cache, only if supported
@@ -474,7 +558,7 @@ void ProgramShaderCache::Init()
File::CreateDir(File::GetUserPath(D_SHADERCACHE_IDX));
std::string cache_filename = StringFromFormat("%sIOGL-%s-shaders.cache", File::GetUserPath(D_SHADERCACHE_IDX).c_str(),
SConfig::GetInstance().m_strGameID.c_str());
SConfig::GetInstance().GetGameID().c_str());
ProgramShaderCacheInserter inserter;
g_program_disk_cache.OpenAndRead(cache_filename, inserter);
@@ -587,7 +671,7 @@ void ProgramShaderCache::CreateHeader()
std::string earlyz_string = "#define FORCE_EARLY_Z \n";
if (g_ActiveConfig.backend_info.bSupportsEarlyZ)
{
if (g_ogl_config.bSupportsEarlyFragmentTests)
if (g_ogl_config.bSupportsImageLoadStore)
{
earlyz_string = "#define FORCE_EARLY_Z layout(early_fragment_tests) in;\n";
if (!is_glsles) // GLES supports this by default
@@ -617,6 +701,7 @@ void ProgramShaderCache::CreateHeader()
"%s\n" // texture buffer
"%s\n" // ES texture buffer
"%s\n" // ES dual source blend
"%s\n" // shader image load store
// Precision defines for GLSL ES
"%s\n"
@@ -625,6 +710,7 @@ void ProgramShaderCache::CreateHeader()
"%s\n"
"%s\n"
"%s\n"
"%s\n"
// Silly differences
"#define float2 vec2\n"
@@ -670,7 +756,7 @@ void ProgramShaderCache::CreateHeader()
"#define UBO_BINDING(packing, x) layout(packing, binding = x)\n"
"#define SAMPLER_BINDING(x) layout(binding = x)\n"
"#define SSBO_BINDING(x) layout(binding = x)\n" :
"#define ATTRIBUTE_LOCATION(x)\n"
"#define ATTRIBUTE_LOCATION(x)\n"
"#define FRAGMENT_OUTPUT_LOCATION(x)\n"
"#define FRAGMENT_OUTPUT_LOCATION_INDEXED(x, y)\n"
"#define UBO_BINDING(packing, x) layout(packing)\n"
@@ -685,11 +771,16 @@ void ProgramShaderCache::CreateHeader()
, v < GLSL_400 && g_ActiveConfig.backend_info.bSupportsSSAA ? "#extension GL_ARB_sample_shading : enable" : ""
, SupportedESTextureBuffer.c_str()
, is_glsles && g_ActiveConfig.backend_info.bSupportsDualSourceBlend ? "#extension GL_EXT_blend_func_extended : enable" : ""
, g_ogl_config.bSupportsImageLoadStore &&
((!is_glsles && v < GLSL_430) || (is_glsles && v < GLSLES_310)) ?
"#extension GL_ARB_shader_image_load_store : enable" :
""
, is_glsles ? "precision highp float;" : ""
, is_glsles ? "precision highp int;" : ""
, is_glsles ? "precision highp sampler2DArray;" : ""
, (is_glsles && g_ActiveConfig.backend_info.bSupportsPaletteConversion) ? "precision highp usamplerBuffer;" : ""
, v > GLSLES_300 ? "precision highp sampler2DMS;" : ""
, v >= GLSLES_310 ? "precision highp image2DArray;" : ""
);
}

View File

@@ -80,7 +80,7 @@ struct SHADER
GLuint glprogid; // OpenGL program id
bool initialized;
void SetProgramVariables();
void SetProgramBindings();
void SetProgramBindings(bool is_compute);
void Bind();
};
@@ -107,6 +107,7 @@ public:
static void GetShaderId(SHADERUID *uid, PIXEL_SHADER_RENDER_MODE render_mode, u32 components, u32 primitive_type);
static bool CompileShader(SHADER &shader, const char* vcode, const char* pcode, const char* gcode = nullptr, const char **macros = nullptr, const u32 macro_count = 0);
static bool CompileComputeShader(SHADER& shader, const std::string& code);
static GLuint CompileSingleShader(GLuint type, const char *code, const char **macros = nullptr, const u32 count = 0);
static void UploadConstants();

View File

@@ -8,6 +8,7 @@
#include <cstdio>
#include <memory>
#include <string>
#include <tuple>
#include <vector>
#include "Common/Atomic.h"
@@ -81,6 +82,11 @@ static void APIENTRY ErrorCallback(GLenum source, GLenum type, GLuint id, GLenum
const char* s_source;
const char* s_type;
// Performance - DualCore driver performance warning:
// DualCore application thread syncing with server thread
if (id == 0x200b0)
return;
switch (source)
{
case GL_DEBUG_SOURCE_API_ARB:
@@ -483,15 +489,16 @@ Renderer::Renderer()
g_ogl_config.bSupportViewportFloat = GLExtensions::Supports("GL_ARB_viewport_array");
g_ogl_config.bSupportsDebug =
GLExtensions::Supports("GL_KHR_debug") || GLExtensions::Supports("GL_ARB_debug_output");
g_ogl_config.bSupports3DTextureStorage =
g_ogl_config.bSupportsTextureStorage = GLExtensions::Supports("GL_ARB_texture_storage");
g_ogl_config.bSupports3DTextureStorageMultisample =
GLExtensions::Supports("GL_ARB_texture_storage_multisample") ||
GLExtensions::Supports("GL_OES_texture_storage_multisample_2d_array");
g_ogl_config.bSupports2DTextureStorage =
g_ogl_config.bSupports2DTextureStorageMultisample =
GLExtensions::Supports("GL_ARB_texture_storage_multisample");
g_ogl_config.bSupportsEarlyFragmentTests =
GLExtensions::Supports("GL_ARB_shader_image_load_store");
g_ogl_config.bSupportsImageLoadStore = GLExtensions::Supports("GL_ARB_shader_image_load_store");
g_ogl_config.bSupportsConservativeDepth = GLExtensions::Supports("GL_ARB_conservative_depth");
g_ogl_config.bSupportsAniso = GLExtensions::Supports("GL_EXT_texture_filter_anisotropic");
g_Config.backend_info.bSupportsComputeShaders = GLExtensions::Supports("GL_ARB_compute_shader");
if (GLInterface->GetMode() == GLInterfaceMode::MODE_OPENGLES3)
{
@@ -518,6 +525,7 @@ Renderer::Renderer()
{
g_ogl_config.eSupportedGLSLVersion = GLSLES_300;
g_ogl_config.bSupportsAEP = false;
g_ogl_config.bSupportsTextureStorage = true;
g_Config.backend_info.bSupportsGeometryShaders = false;
}
else if (GLExtensions::Version() == 310)
@@ -525,16 +533,18 @@ Renderer::Renderer()
g_ogl_config.eSupportedGLSLVersion = GLSLES_310;
g_ogl_config.bSupportsAEP = GLExtensions::Supports("GL_ANDROID_extension_pack_es31a");
g_Config.backend_info.bSupportsBindingLayout = true;
g_ogl_config.bSupportsEarlyFragmentTests = true;
g_ogl_config.bSupportsImageLoadStore = true;
g_Config.backend_info.bSupportsGeometryShaders = g_ogl_config.bSupportsAEP;
g_Config.backend_info.bSupportsComputeShaders = true;
g_Config.backend_info.bSupportsGSInstancing =
g_Config.backend_info.bSupportsGeometryShaders && g_ogl_config.SupportedESPointSize > 0;
g_Config.backend_info.bSupportsSSAA = g_ogl_config.bSupportsAEP;
g_Config.backend_info.bSupportsBBox = true;
g_ogl_config.bSupportsMSAA = true;
g_ogl_config.bSupports2DTextureStorage = true;
g_ogl_config.bSupportsTextureStorage = true;
g_ogl_config.bSupports2DTextureStorageMultisample = true;
if (g_ActiveConfig.iStereoMode > 0 && g_ActiveConfig.iMultisamples > 1 &&
!g_ogl_config.bSupports3DTextureStorage)
!g_ogl_config.bSupports3DTextureStorageMultisample)
{
// GLES 3.1 can't support stereo rendering and MSAA
OSD::AddMessage("MSAA Stereo rendering isn't supported by your GPU.", 10000);
@@ -546,8 +556,9 @@ Renderer::Renderer()
g_ogl_config.eSupportedGLSLVersion = GLSLES_320;
g_ogl_config.bSupportsAEP = GLExtensions::Supports("GL_ANDROID_extension_pack_es31a");
g_Config.backend_info.bSupportsBindingLayout = true;
g_ogl_config.bSupportsEarlyFragmentTests = true;
g_ogl_config.bSupportsImageLoadStore = true;
g_Config.backend_info.bSupportsGeometryShaders = true;
g_Config.backend_info.bSupportsComputeShaders = true;
g_Config.backend_info.bSupportsGSInstancing = g_ogl_config.SupportedESPointSize > 0;
g_Config.backend_info.bSupportsPaletteConversion = true;
g_Config.backend_info.bSupportsSSAA = true;
@@ -556,8 +567,9 @@ Renderer::Renderer()
g_ogl_config.bSupportsGLBaseVertex = true;
g_ogl_config.bSupportsDebug = true;
g_ogl_config.bSupportsMSAA = true;
g_ogl_config.bSupports2DTextureStorage = true;
g_ogl_config.bSupports3DTextureStorage = true;
g_ogl_config.bSupportsTextureStorage = true;
g_ogl_config.bSupports2DTextureStorageMultisample = true;
g_ogl_config.bSupports3DTextureStorageMultisample = true;
}
}
else
@@ -573,8 +585,7 @@ Renderer::Renderer()
else if (GLExtensions::Version() == 300)
{
g_ogl_config.eSupportedGLSLVersion = GLSL_130;
g_ogl_config.bSupportsEarlyFragmentTests =
false; // layout keyword is only supported on glsl150+
g_ogl_config.bSupportsImageLoadStore = false; // layout keyword is only supported on glsl150+
g_ogl_config.bSupportsConservativeDepth =
false; // layout keyword is only supported on glsl150+
g_Config.backend_info.bSupportsGeometryShaders =
@@ -583,8 +594,7 @@ Renderer::Renderer()
else if (GLExtensions::Version() == 310)
{
g_ogl_config.eSupportedGLSLVersion = GLSL_140;
g_ogl_config.bSupportsEarlyFragmentTests =
false; // layout keyword is only supported on glsl150+
g_ogl_config.bSupportsImageLoadStore = false; // layout keyword is only supported on glsl150+
g_ogl_config.bSupportsConservativeDepth =
false; // layout keyword is only supported on glsl150+
g_Config.backend_info.bSupportsGeometryShaders =
@@ -598,10 +608,27 @@ Renderer::Renderer()
{
g_ogl_config.eSupportedGLSLVersion = GLSL_330;
}
else if (GLExtensions::Version() >= 430)
{
// TODO: We should really parse the GL_SHADING_LANGUAGE_VERSION token.
g_ogl_config.eSupportedGLSLVersion = GLSL_430;
g_ogl_config.bSupportsTextureStorage = true;
g_ogl_config.bSupportsImageLoadStore = true;
g_Config.backend_info.bSupportsSSAA = true;
// Compute shaders are core in GL4.3.
g_Config.backend_info.bSupportsComputeShaders = true;
}
else
{
g_ogl_config.eSupportedGLSLVersion = GLSL_400;
g_Config.backend_info.bSupportsSSAA = true;
if (GLExtensions::Version() == 420)
{
// Texture storage and shader image load/store are core in GL4.2.
g_ogl_config.bSupportsTextureStorage = true;
g_ogl_config.bSupportsImageLoadStore = true;
}
}
g_Config.backend_info.bSupportedFormats[PC_TEX_FMT_DXT1] = GLExtensions::Supports("GL_EXT_texture_compression_s3tc");
g_Config.backend_info.bSupportedFormats[PC_TEX_FMT_DXT3] = g_Config.backend_info.bSupportedFormats[PC_TEX_FMT_DXT1];
@@ -613,12 +640,19 @@ Renderer::Renderer()
// Either method can do early-z tests. See PixelShaderGen for details.
g_Config.backend_info.bSupportsEarlyZ =
g_ogl_config.bSupportsEarlyFragmentTests || g_ogl_config.bSupportsConservativeDepth;
g_ogl_config.bSupportsImageLoadStore || g_ogl_config.bSupportsConservativeDepth;
glGetIntegerv(GL_MAX_SAMPLES, &g_ogl_config.max_samples);
if (g_ogl_config.max_samples < 1 || !g_ogl_config.bSupportsMSAA)
g_ogl_config.max_samples = 1;
// We require texel buffers, image load store, and compute shaders to enable GPU texture decoding.
// If the driver doesn't expose the extensions, but supports GL4.3/GLES3.1, it will still be
// enabled in the version check below.
g_Config.backend_info.bSupportsGPUTextureDecoding =
g_Config.backend_info.bSupportsPaletteConversion &&
g_Config.backend_info.bSupportsComputeShaders && g_ogl_config.bSupportsImageLoadStore;
if (g_ogl_config.bSupportsDebug)
{
if (GLExtensions::Supports("GL_KHR_debug"))
@@ -690,28 +724,65 @@ Renderer::Renderer()
s_last_xfb_mode = g_ActiveConfig.bUseRealXFB;
// Decide framebuffer size
s_backbuffer_width = static_cast<int>(std::max(GLInterface->GetBackBufferWidth(), 16u));
s_backbuffer_height = static_cast<int>(std::max(GLInterface->GetBackBufferHeight(), 16u));
m_backbuffer_width = static_cast<int>(std::max(GLInterface->GetBackBufferWidth(), 16u));
m_backbuffer_height = static_cast<int>(std::max(GLInterface->GetBackBufferHeight(), 16u));
// Handle VSync on/off
s_vsync = g_ActiveConfig.IsVSync();
if (!DriverDetails::HasBug(DriverDetails::BUG_BROKEN_VSYNC))
GLInterface->SwapInterval(s_vsync);
// Because of the fixed framebuffer size we need to disable the resolution
// options while running
g_Config.bRunning = true;
UpdateActiveConfig();
ClearEFBCache();
}
Renderer::~Renderer()
{
FlushFrameDump();
FinishFrameData();
DestroyFrameDumpResources();
}
void Renderer::Shutdown()
{
g_framebuffer_manager.reset();
g_Config.bRunning = false;
UpdateActiveConfig();
s_raster_font.reset();
m_post_processor.reset();
OpenGL_DeleteAttributelessVAO();
}
void Renderer::Init()
{
// TODO: Move these somewhere else?
FramebufferManagerBase::SetLastXfbWidth(MAX_XFB_WIDTH);
FramebufferManagerBase::SetLastXfbHeight(MAX_XFB_HEIGHT);
UpdateDrawRectangle();
s_last_efb_scale = g_ActiveConfig.iEFBScale;
m_last_efb_scale = g_ActiveConfig.iEFBScale;
CalculateTargetSize();
PixelShaderManager::SetEfbScaleChanged();
// Because of the fixed framebuffer size we need to disable the resolution
// options while running
g_Config.bRunning = true;
// Initialize the FramebufferManager
g_framebuffer_manager =
std::make_unique<FramebufferManager>(m_target_width, m_target_height, s_MSAASamples);
s_raster_font = std::make_unique<RasterFont>();
OpenGL_CreateAttributelessVAO();
m_post_processor = std::make_unique<OGLPostProcessor>();
if (!m_post_processor->Initialize())
PanicAlert("OGL: Failed to initialize post processor.");
glStencilFunc(GL_ALWAYS, 0, 0);
glBlendFunc(GL_ONE, GL_ONE);
@@ -739,52 +810,6 @@ Renderer::Renderer()
glScissor(0, 0, GetTargetWidth(), GetTargetHeight());
glBlendColor(0, 0, 0, 0.5f);
glClearDepthf(1.0f);
UpdateActiveConfig();
ClearEFBCache();
m_bColorMaskChanged = true;
m_bBlendModeChanged = true;
m_bBlendModeForce = true;
m_bScissorRectChanged = true;
m_bViewPortChanged = true;
m_bGenerationModeChanged = true;
m_bDepthModeChanged = true;
m_bLogicOpModeChanged = true;
m_bViewPortChangedRequested = true;
}
Renderer::~Renderer()
{
FlushFrameDump();
FinishFrameData();
DestroyFrameDumpResources();
}
void Renderer::Shutdown()
{
g_framebuffer_manager.reset();
g_Config.bRunning = false;
UpdateActiveConfig();
s_raster_font.reset();
m_post_processor.reset();
OpenGL_DeleteAttributelessVAO();
}
void Renderer::Init()
{
// Initialize the FramebufferManager
g_framebuffer_manager =
std::make_unique<FramebufferManager>(s_target_width, s_target_height, s_MSAASamples);
s_raster_font = std::make_unique<RasterFont>();
OpenGL_CreateAttributelessVAO();
m_post_processor = std::make_unique<OGLPostProcessor>();
if (!m_post_processor->Initialize())
PanicAlert("OGL: Failed to initialize post processor.");
}
void Renderer::RenderText(const std::string& text, int left, int top, u32 color)
@@ -821,14 +846,14 @@ TargetRectangle Renderer::ConvertEFBRectangle(const EFBRectangle& rc)
void Renderer::_SetScissorRect()
{
m_bScissorRectChanged = false;
glScissor(m_ScissorRect.left, m_ScissorRect.bottom, m_ScissorRect.GetWidth(), m_ScissorRect.GetHeight());
TargetRectangle targetrc = ConvertEFBRectangle(m_ScissorRect);
glScissor(targetrc.left, targetrc.bottom, targetrc.GetWidth(), targetrc.GetHeight());
}
void Renderer::SetScissorRect(const TargetRectangle& trc)
void Renderer::SetScissorRect(const EFBRectangle& trc)
{
m_bScissorRectChanged = true;
m_ScissorRect = trc;
}
void Renderer::_SetColorMask()
@@ -1075,12 +1100,12 @@ u16 Renderer::BBoxRead(int index)
if (index < 2)
{
// left/right
value = value * EFB_WIDTH / s_target_width;
value = value * EFB_WIDTH / m_target_width;
}
else
{
// up/down -- we have to swap up and down
value = value * EFB_HEIGHT / s_target_height;
value = value * EFB_HEIGHT / m_target_height;
value = EFB_HEIGHT - value - 1;
}
if (index & 1)
@@ -1096,13 +1121,13 @@ void Renderer::BBoxWrite(int index, u16 _value)
value--;
if (index < 2)
{
value = value * s_target_width / EFB_WIDTH;
value = value * m_target_width / EFB_WIDTH;
}
else
{
index ^= 1; // swap 2 and 3 for top/bottom
value = EFB_HEIGHT - value - 1;
value = value * s_target_height / EFB_HEIGHT;
value = value * m_target_height / EFB_HEIGHT;
}
BBox::Set(index, value);
@@ -1146,7 +1171,7 @@ void Renderer::_SetViewport()
m_viewport.Height *= -1;
}
}
if (m_bViewPortChanged)
{
@@ -1216,9 +1241,9 @@ void Renderer::BlitScreen(const TargetRectangle& dst_rect, const TargetRectangle
// Top-and-Bottom mode needs to compensate for inverted vertical screen coordinates.
if (g_ActiveConfig.iStereoMode == STEREO_TAB)
ConvertStereoRectangle(dst_rect, rightRc, leftRc);
std::tie(rightRc, leftRc) = ConvertStereoRectangle(dst_rect);
else
ConvertStereoRectangle(dst_rect, leftRc, rightRc);
std::tie(leftRc, rightRc) = ConvertStereoRectangle(dst_rect);
m_post_processor->BlitScreen(leftRc, dst_size, dst_texture, src_rect, src_size, src_texture, src_depth_texture, 0, gamma);
m_post_processor->BlitScreen(rightRc, dst_size, dst_texture, src_rect, src_size, src_texture, src_depth_texture, 1, gamma);
@@ -1382,7 +1407,7 @@ void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight,
glDisable(GL_DEBUG_OUTPUT);
}
if ((!XFBWrited && !g_ActiveConfig.RealXFBEnabled()) || !fbWidth || !fbHeight)
if ((!m_xfb_written && !g_ActiveConfig.RealXFBEnabled()) || !fbWidth || !fbHeight)
{
Core::Callback_VideoCopiedToXFB(false);
return;
@@ -1406,7 +1431,7 @@ void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight,
std::swap(flipped_trc.top, flipped_trc.bottom);
// Copy the framebuffer to screen.
const TargetSize dst_size = {s_target_width, s_target_height};
const TargetSize dst_size = {m_target_width, m_target_height};
DrawFrame(flipped_trc, rc, xfbAddr, xfbSourceList, xfbCount, 0, dst_size, fbWidth, fbStride, fbHeight, Gamma);
// The FlushFrameDump call here is necessary even after frame dumping is stopped.
@@ -1453,13 +1478,13 @@ void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight,
bool window_resized = false;
int window_width = static_cast<int>(std::max(GLInterface->GetBackBufferWidth(), 16u));
int window_height = static_cast<int>(std::max(GLInterface->GetBackBufferHeight(), 16u));
if (window_width != s_backbuffer_width || window_height != s_backbuffer_height ||
s_last_efb_scale != g_ActiveConfig.iEFBScale)
if (window_width != m_backbuffer_width || window_height != m_backbuffer_height ||
m_last_efb_scale != g_ActiveConfig.iEFBScale)
{
window_resized = true;
s_backbuffer_width = window_width;
s_backbuffer_height = window_height;
s_last_efb_scale = g_ActiveConfig.iEFBScale;
m_backbuffer_width = window_width;
m_backbuffer_height = window_height;
m_last_efb_scale = g_ActiveConfig.iEFBScale;
}
bool target_size_changed = CalculateTargetSize();
if (target_size_changed || xfbchanged || window_resized ||
@@ -1489,7 +1514,7 @@ void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight,
g_framebuffer_manager.reset();
g_framebuffer_manager =
std::make_unique<FramebufferManager>(s_target_width, s_target_height, s_MSAASamples);
std::make_unique<FramebufferManager>(m_target_width, m_target_height, s_MSAASamples);
PixelShaderManager::SetEfbScaleChanged();
@@ -1588,7 +1613,7 @@ void Renderer::DrawEFB(const TargetRectangle& t_rc, const EFBRectangle& source_r
TargetRectangle target_rc = { t_rc.left, t_rc.top, t_rc.right, t_rc.bottom };
// for msaa mode, we must resolve the efb content to non-msaa
GLuint tex = FramebufferManager::ResolveAndGetRenderTarget(source_rc);
TargetSize tex_size(s_target_width, s_target_height);
TargetSize tex_size(m_target_width, m_target_height);
// Apply post-processing.
// If enabled, blit_tex will be replaced with an internal texture from the post-processor,
// leaving the original texture unmodified, should it be required next frame.
@@ -2102,11 +2127,6 @@ void Renderer::SetLogicOpMode()
m_bLogicOpModeChanged = true;
}
void Renderer::SetDitherMode()
{
}
void Renderer::SetSamplerState(int stage, int texindex, bool custom_tex)
{
auto const& tex = bpmem.tex[texindex];

View File

@@ -21,6 +21,7 @@ enum GLSL_VERSION
GLSL_150,
GLSL_330,
GLSL_400, // and above
GLSL_430,
GLSLES_300, // GLES 3.0
GLSLES_310, // GLES 3.1
GLSLES_320, // GLES 3.2
@@ -49,10 +50,11 @@ struct VideoConfig
bool bSupportsCopySubImage;
u8 SupportedESPointSize;
ES_TEXBUF_TYPE SupportedESTextureBuffer;
bool bSupports2DTextureStorage;
bool bSupports3DTextureStorage;
bool bSupportsEarlyFragmentTests;
bool bSupportsTextureStorage;
bool bSupports2DTextureStorageMultisample;
bool bSupports3DTextureStorageMultisample;
bool bSupportsConservativeDepth;
bool bSupportsImageLoadStore;
bool bSupportsAniso;
const char* gl_vendor;
@@ -69,16 +71,15 @@ public:
Renderer();
~Renderer();
static void Init();
static void Shutdown();
void Init() override;
void Shutdown() override;
void SetColorMask() override;
void SetBlendMode(bool forceUpdate) override;
void SetScissorRect(const TargetRectangle& rc) override;
void SetScissorRect(const EFBRectangle& rc) override;
void SetGenerationMode() override;
void SetDepthMode() override;
void SetLogicOpMode() override;
void SetDitherMode() override;
void SetSamplerState(int stage, int texindex, bool custom_tex) override;
void SetInterlacingMode() override;
void SetViewport() override;
@@ -119,17 +120,17 @@ private:
float NearZ;
float FarZ;
};
bool m_bColorMaskChanged;
bool m_bBlendModeChanged;
bool m_bBlendModeForce;
bool m_bScissorRectChanged;
bool m_bViewPortChanged;
TargetRectangle m_ScissorRect;
ViewPort m_viewport;
bool m_bGenerationModeChanged;
bool m_bDepthModeChanged;
bool m_bLogicOpModeChanged;
bool m_bViewPortChangedRequested;
bool m_bColorMaskChanged = true;
bool m_bBlendModeChanged = true;
bool m_bBlendModeForce = true;
bool m_bScissorRectChanged = true;
bool m_bViewPortChanged = true;
EFBRectangle m_ScissorRect{};
ViewPort m_viewport{};
bool m_bGenerationModeChanged = true;
bool m_bDepthModeChanged = true;
bool m_bLogicOpModeChanged = true;
bool m_bViewPortChangedRequested = true;
void _SetColorMask();
void _SetBlendMode(bool forceUpdate);

View File

@@ -21,6 +21,7 @@
#include "Core/HW/Memmap.h"
#include "VideoBackends/OGL/FramebufferManager.h"
#include "VideoBackends/OGL/GPUTimer.h"
#include "Common/GL/GLInterfaceBase.h"
#include "VideoBackends/OGL/ProgramShaderCache.h"
#include "VideoBackends/OGL/Render.h"
@@ -32,6 +33,7 @@
#include "VideoCommon/BPStructs.h"
#include "VideoCommon/HiresTextures.h"
#include "VideoCommon/ImageWrite.h"
#include "VideoCommon/TextureConversionShader.h"
#include "VideoCommon/Statistics.h"
#include "VideoCommon/TextureDecoder.h"
#include "VideoCommon/TextureScalerCommon.h"
@@ -64,9 +66,29 @@ static GLuint s_palette_resolv_texture;
static GLuint s_palette_buffer_offset_uniform[3];
static GLuint s_palette_multiplier_uniform[3];
static GLuint s_palette_copy_position_uniform[3];
static std::unique_ptr<TextureScaler> s_scaler;
static u32 s_last_pallet_Buffer;
static TlutFormat s_last_TlutFormat = TlutFormat::GX_TL_IA8;
struct TextureDecodingProgramInfo
{
const TextureConversionShader::DecodingShaderInfo* base_info = nullptr;
SHADER program;
GLint uniform_dst_size = -1;
GLint uniform_src_size = -1;
GLint uniform_src_row_stride = -1;
GLint uniform_src_offset = -1;
GLint uniform_palette_offset = -1;
bool valid = false;
};
//#define TIME_TEXTURE_DECODING 1
static std::map<std::pair<u32, u32>, TextureDecodingProgramInfo> s_texture_decoding_program_info;
static std::array<GLuint, TextureConversionShader::BUFFER_FORMAT_COUNT>
s_texture_decoding_buffer_views;
static void CreateTextureDecodingResources();
static void DestroyTextureDecodingResources();
bool SaveTexture(const std::string& filename, u32 textarget, u32 tex, int virtual_width, int virtual_height, u32 level, bool compressed)
{
if (GLInterface->GetMode() != GLInterfaceMode::MODE_OPENGL)
@@ -169,81 +191,95 @@ void TextureCache::TCacheEntry::SetFormat()
case PC_TEX_FMT_BGRA32:
gl_format = GL_BGRA;
gl_iformat = GL_RGBA;
gl_siformat = GL_RGBA8;
gl_type = GL_UNSIGNED_BYTE;
break;
case PC_TEX_FMT_RGBA32:
gl_format = GL_RGBA;
gl_iformat = GL_RGBA;
gl_siformat = GL_RGBA8;
gl_type = GL_UNSIGNED_BYTE;
break;
case PC_TEX_FMT_I4_AS_I8:
gl_format = GL_LUMINANCE;
gl_iformat = GL_INTENSITY4;
gl_siformat = GL_R8;
gl_type = GL_UNSIGNED_BYTE;
break;
case PC_TEX_FMT_IA4_AS_IA8:
gl_format = GL_LUMINANCE_ALPHA;
gl_iformat = GL_LUMINANCE4_ALPHA4;
gl_siformat = GL_RG8;
gl_type = GL_UNSIGNED_BYTE;
break;
case PC_TEX_FMT_I8:
gl_format = GL_LUMINANCE;
gl_iformat = GL_INTENSITY8;
gl_siformat = GL_R8;
gl_type = GL_UNSIGNED_BYTE;
break;
case PC_TEX_FMT_IA8:
gl_format = GL_LUMINANCE_ALPHA;
gl_iformat = GL_LUMINANCE8_ALPHA8;
gl_siformat = GL_RG8;
gl_type = GL_UNSIGNED_BYTE;
break;
case PC_TEX_FMT_RGB565:
gl_format = GL_RGB;
gl_iformat = GL_RGB;
gl_siformat = GL_RGB5;
gl_type = GL_UNSIGNED_SHORT_5_6_5;
break;
case PC_TEX_FMT_DXT1:
gl_format = 0;
gl_iformat = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
gl_type = 0;
gl_format = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
gl_iformat = GL_RGB;
gl_siformat = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
gl_type = GL_UNSIGNED_BYTE;
compressed = true;
break;
case PC_TEX_FMT_DXT3:
gl_format = 0;
gl_iformat = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
gl_type = 0;
gl_format = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
gl_iformat = GL_RGBA;
gl_siformat = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
gl_type = GL_UNSIGNED_BYTE;
compressed = true;
break;
case PC_TEX_FMT_DXT5:
gl_format = 0;
gl_iformat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
gl_type = 0;
gl_format = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
gl_iformat = GL_RGBA;
gl_siformat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
gl_type = GL_UNSIGNED_BYTE;
compressed = true;
break;
case PC_TEX_FMT_DEPTH_FLOAT:
gl_format = GL_DEPTH_COMPONENT32F;
gl_iformat = GL_DEPTH_COMPONENT;
gl_siformat = GL_DEPTH_COMPONENT32;
gl_type = GL_FLOAT;
compressed = false;
break;
case PC_TEX_FMT_R_FLOAT:
gl_format = GL_R32F;
gl_iformat = GL_R;
gl_iformat = GL_RED;
gl_siformat = GL_R32F;
gl_type = GL_FLOAT;
compressed = false;
break;
case PC_TEX_FMT_RGBA16_FLOAT:
gl_format = GL_RGBA16F;
gl_iformat = GL_RGBA;
gl_siformat = GL_RGBA16F;
gl_type = GL_FLOAT;
compressed = false;
break;
case PC_TEX_FMT_RGBA_FLOAT:
gl_format = GL_RGBA32F;
gl_iformat = GL_RGBA;
gl_siformat = GL_RGBA32F;
gl_type = GL_FLOAT;
compressed = false;
break;
@@ -258,11 +294,24 @@ TextureCache::TCacheEntryBase* TextureCache::CreateTexture(const TCacheEntryConf
glBindTexture(GL_TEXTURE_2D_ARRAY, entry->texture);
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAX_LEVEL, config.levels - 1);
entry->SetFormat();
if (g_ogl_config.bSupportsTextureStorage)
{
glTexStorage3D(GL_TEXTURE_2D_ARRAY, config.levels, entry->gl_siformat, config.width, config.height,
config.layers);
}
if (config.rendertarget)
{
for (u32 level = 0; level < config.levels; level++)
if (!g_ogl_config.bSupportsTextureStorage)
{
glTexImage3D(GL_TEXTURE_2D_ARRAY, level, entry->gl_format, config.width, config.height, config.layers, 0, entry->gl_iformat, entry->gl_type, nullptr);
for (u32 level = 0; level < config.levels; level++)
{
glTexImage3D(GL_TEXTURE_2D_ARRAY, level, entry->gl_format,
std::max(config.width >> level, 1u),
std::max(config.height >> level, 1u),
config.layers, 0, entry->gl_iformat, entry->gl_type, nullptr);
}
}
glGenFramebuffers(1, &entry->framebuffer);
FramebufferManager::SetFramebuffer(entry->framebuffer);
@@ -275,6 +324,11 @@ TextureCache::TCacheEntryBase* TextureCache::CreateTexture(const TCacheEntryConf
glGenTextures(1, &entry->nrm_texture);
glBindTexture(GL_TEXTURE_2D_ARRAY, entry->nrm_texture);
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAX_LEVEL, config.levels - 1);
if (g_ogl_config.bSupportsTextureStorage)
{
glTexStorage3D(GL_TEXTURE_2D_ARRAY, config.levels, entry->gl_siformat, config.width, config.height,
config.layers);
}
}
}
TextureCache::SetStage();
@@ -355,12 +409,19 @@ void TextureCache::TCacheEntry::Load(const u8* src, u32 width, u32 height,
glPixelStorei(GL_UNPACK_COMPRESSED_BLOCK_SIZE, blocksize);
glPixelStorei(GL_UNPACK_ROW_LENGTH, expanded_width);
}
glCompressedTexImage3D(GL_TEXTURE_2D_ARRAY, level, gl_iformat,
width, height, 1, 0, ((width + 3) >> 2) * ((height + 3) >> 2) * blocksize, src);
if (g_ogl_config.bSupportsTextureStorage)
{
glCompressedTexSubImage3D(GL_TEXTURE_2D_ARRAY, level, 0, 0, 0,
width, height, 1, gl_format, ((width + 3) >> 2) * ((height + 3) >> 2) * blocksize, src);
}
else
{
glCompressedTexImage3D(GL_TEXTURE_2D_ARRAY, level, gl_format,
width, height, 1, 0, ((width + 3) >> 2) * ((height + 3) >> 2) * blocksize, src);
}
if (expanded_width != width)
{
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
glPixelStorei(GL_UNPACK_ALIGNMENT, 0);
glPixelStorei(GL_UNPACK_COMPRESSED_BLOCK_WIDTH, 0);
glPixelStorei(GL_UNPACK_COMPRESSED_BLOCK_HEIGHT, 0);
glPixelStorei(GL_UNPACK_COMPRESSED_BLOCK_DEPTH, 0);
@@ -372,7 +433,16 @@ void TextureCache::TCacheEntry::Load(const u8* src, u32 width, u32 height,
{
if (expanded_width != width)
glPixelStorei(GL_UNPACK_ROW_LENGTH, expanded_width);
glTexImage3D(GL_TEXTURE_2D_ARRAY, level, gl_iformat, width, height, 1, 0, gl_format, gl_type, src);
if (g_ogl_config.bSupportsTextureStorage)
{
glTexSubImage3D(GL_TEXTURE_2D_ARRAY, level, 0, 0, 0, width, height, 1, gl_format,
gl_type, src);
}
else
{
glTexImage3D(GL_TEXTURE_2D_ARRAY, level, gl_iformat, width, height, 1, 0, gl_format,
gl_type, src);
}
if (expanded_width != width)
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
}
@@ -393,46 +463,34 @@ void TextureCache::TCacheEntry::LoadMaterialMap(const u8* src, u32 width, u32 he
case PC_TEX_FMT_DXT3:
case PC_TEX_FMT_DXT5:
{
glCompressedTexImage3D(GL_TEXTURE_2D_ARRAY, level, gl_iformat,
width, height, 1, 0, ((width + 3) >> 2) * ((height + 3) >> 2) * blocksize, src);
if (g_ogl_config.bSupportsTextureStorage)
{
glCompressedTexSubImage3D(GL_TEXTURE_2D_ARRAY, level, 0, 0, 0,
width, height, 1, gl_format, ((width + 3) >> 2) * ((height + 3) >> 2) * blocksize, src);
}
else
{
glCompressedTexImage3D(GL_TEXTURE_2D_ARRAY, level, gl_format,
width, height, 1, 0, ((width + 3) >> 2) * ((height + 3) >> 2) * blocksize, src);
}
}
break;
default:
glTexImage3D(GL_TEXTURE_2D_ARRAY, level, gl_iformat, width, height, 1, 0, gl_format, gl_type, src);
if (g_ogl_config.bSupportsTextureStorage)
{
glTexSubImage3D(GL_TEXTURE_2D_ARRAY, level, 0, 0, 0, width, height, 1, gl_format,
gl_type, src);
}
else
{
glTexImage3D(GL_TEXTURE_2D_ARRAY, level, gl_format, width, height, 1, 0, gl_iformat,
gl_type, src);
}
break;
}
TextureCache::SetStage();
}
void TextureCache::TCacheEntry::Load(const u8* src, u32 width, u32 height, u32 expandedWidth,
u32 expandedHeight, const s32 texformat, const u32 tlutaddr, const TlutFormat tlutfmt, u32 level)
{
u8* data = g_texture_cache->GetTemporalBuffer();
TexDecoder_Decode(data, src, expandedWidth, expandedHeight, texformat, tlutaddr, tlutfmt, PC_TEX_FMT_RGBA32 == config.pcformat, compressed);
if (is_scaled)
{
data = (u8*)s_scaler->Scale((u32*)data, expandedWidth, height);
width *= g_ActiveConfig.iTexScalingFactor;
height *= g_ActiveConfig.iTexScalingFactor;
expandedWidth *= g_ActiveConfig.iTexScalingFactor;
}
Load(data, width, height, expandedWidth, level);
}
void TextureCache::TCacheEntry::LoadFromTmem(const u8* ar_src, const u8* gb_src, u32 width, u32 height,
u32 expanded_width, u32 expanded_Height, u32 level)
{
u8* data = g_texture_cache->GetTemporalBuffer();
TexDecoder_DecodeRGBA8FromTmem((u32*)data, ar_src, gb_src, expanded_width, expanded_Height);
if (is_scaled)
{
data = (u8*)s_scaler->Scale((u32*)data, expanded_width, height);
width *= g_ActiveConfig.iTexScalingFactor;
height *= g_ActiveConfig.iTexScalingFactor;
expanded_width *= g_ActiveConfig.iTexScalingFactor;
}
Load(data, width, height, expanded_width, level);
}
void TextureCache::TCacheEntry::FromRenderTarget(bool is_depth_copy, const EFBRectangle& srcRect,
bool scaleByHalf, unsigned int cbufid, const float *colmat, u32 width, u32 height)
{
@@ -484,21 +542,12 @@ void TextureCache::TCacheEntry::FromRenderTarget(bool is_depth_copy, const EFBRe
g_renderer->RestoreAPIState();
}
void TextureCache::CopyEFB(u8* dst, u32 format, u32 native_width, u32 bytes_per_row, u32 num_blocks_y, u32 memory_stride,
bool is_depth_copy, const EFBRectangle& srcRect,
bool isIntensity, bool scaleByHalf)
void TextureCache::CopyEFB(u8* dst, const EFBCopyFormat& format, u32 native_width, u32 bytes_per_row,
u32 num_blocks_y, u32 memory_stride, bool is_depth_copy,
const EFBRectangle& src_rect, bool scale_by_half)
{
TextureConverter::EncodeToRamFromTexture(
dst,
format,
native_width,
bytes_per_row,
num_blocks_y,
memory_stride,
is_depth_copy,
isIntensity,
scaleByHalf,
srcRect);
TextureConverter::EncodeToRamFromTexture(dst, format, native_width, bytes_per_row, num_blocks_y,
memory_stride, is_depth_copy, src_rect, scale_by_half);
}
bool TextureCache::Palettize(TCacheEntryBase* src_entry, const TCacheEntryBase* base_entry)
@@ -544,22 +593,24 @@ TextureCache::TextureCache()
gtex = -1;
if (g_ActiveConfig.backend_info.bSupportsPaletteConversion)
{
s32 buffer_size = 1024 * 1024;
s32 buffer_size_mb = (g_ActiveConfig.backend_info.bSupportsGPUTextureDecoding ? 32 : 1);
s32 buffer_size = buffer_size_mb * 1024 * 1024;
s32 max_buffer_size = 0;
// The minimum MAX_TEXTURE_BUFFER_SIZE that the spec mandates
// is 65KB, we are asking for a 1MB buffer here.
// Make sure to check the maximum size and if it is below 1MB
// then use the maximum the hardware supports instead.
// The minimum MAX_TEXTURE_BUFFER_SIZE that the spec mandates is 65KB, we are asking for a 1MB
// buffer here. This buffer is also used as storage for undecoded textures when compute shader
// texture decoding is enabled, in which case the requested size is 32MB.
glGetIntegerv(GL_MAX_TEXTURE_BUFFER_SIZE, &max_buffer_size);
// Clamp the buffer size to the maximum size that the driver supports.
buffer_size = std::min(buffer_size, max_buffer_size);
s_palette_stream_buffer = StreamBuffer::Create(GL_TEXTURE_BUFFER, buffer_size);
glGenTextures(1, &s_palette_resolv_texture);
glBindTexture(GL_TEXTURE_BUFFER, s_palette_resolv_texture);
glTexBuffer(GL_TEXTURE_BUFFER, GL_R16UI, s_palette_stream_buffer->m_buffer);
CreateTextureDecodingResources();
}
s_scaler = std::make_unique<TextureScaler>();
}
bool TextureCache::CompileShaders()
@@ -781,12 +832,12 @@ void TextureCache::DeleteShaders()
TextureCache::~TextureCache()
{
DeleteShaders();
DestroyTextureDecodingResources();
if (g_ActiveConfig.backend_info.bSupportsPaletteConversion)
{
s_palette_stream_buffer.reset();
glDeleteTextures(1, &s_palette_resolv_texture);
}
s_scaler.reset();
}
void TextureCache::LoadLut(u32 lutFmt, void* addr, u32 size)
@@ -824,4 +875,158 @@ void TextureCache::SetStage()
glActiveTexture(GL_TEXTURE0 + s_ActiveTexture);
}
static const std::string decoding_vertex_shader = R"(
void main()
{
vec2 rawpos = vec2(gl_VertexID&1, gl_VertexID&2);
gl_Position = vec4(rawpos*2.0-1.0, 0.0, 1.0);
}
)";
void CreateTextureDecodingResources()
{
static const GLenum gl_view_types[TextureConversionShader::BUFFER_FORMAT_COUNT] = {
GL_R8UI, // BUFFER_FORMAT_R8_UINT
GL_R16UI, // BUFFER_FORMAT_R16_UINT
GL_RG32UI, // BUFFER_FORMAT_R32G32_UINT
};
glGenTextures(TextureConversionShader::BUFFER_FORMAT_COUNT,
s_texture_decoding_buffer_views.data());
for (size_t i = 0; i < TextureConversionShader::BUFFER_FORMAT_COUNT; i++)
{
glBindTexture(GL_TEXTURE_BUFFER, s_texture_decoding_buffer_views[i]);
glTexBuffer(GL_TEXTURE_BUFFER, gl_view_types[i], s_palette_stream_buffer->m_buffer);
}
}
void DestroyTextureDecodingResources()
{
glDeleteTextures(TextureConversionShader::BUFFER_FORMAT_COUNT,
s_texture_decoding_buffer_views.data());
s_texture_decoding_buffer_views.fill(0);
s_texture_decoding_program_info.clear();
}
bool TextureCache::SupportsGPUTextureDecode(TextureFormat format, TlutFormat palette_format)
{
auto key = std::make_pair(static_cast<u32>(format), static_cast<u32>(palette_format));
auto iter = s_texture_decoding_program_info.find(key);
if (iter != s_texture_decoding_program_info.end())
return iter->second.valid;
TextureDecodingProgramInfo info;
info.base_info = TextureConversionShader::GetDecodingShaderInfo(format);
if (!info.base_info)
{
s_texture_decoding_program_info.emplace(key, info);
return false;
}
std::string shader_source =
TextureConversionShader::GenerateDecodingShader(format, palette_format, API_OPENGL);
if (shader_source.empty())
{
s_texture_decoding_program_info.emplace(key, info);
return false;
}
if (!ProgramShaderCache::CompileComputeShader(info.program, shader_source))
{
s_texture_decoding_program_info.emplace(key, info);
return false;
}
info.uniform_dst_size = glGetUniformLocation(info.program.glprogid, "u_dst_size");
info.uniform_src_size = glGetUniformLocation(info.program.glprogid, "u_src_size");
info.uniform_src_offset = glGetUniformLocation(info.program.glprogid, "u_src_offset");
info.uniform_src_row_stride = glGetUniformLocation(info.program.glprogid, "u_src_row_stride");
info.uniform_palette_offset = glGetUniformLocation(info.program.glprogid, "u_palette_offset");
info.valid = true;
s_texture_decoding_program_info.emplace(key, info);
return true;
}
bool TextureCache::TCacheEntry::DecodeTextureOnGPU(u32 dst_level, const u8* data,
u32 data_size, TextureFormat format, u32 width, u32 height,
u32 aligned_width, u32 aligned_height, u32 row_stride,
const u8* palette, TlutFormat palette_format)
{
auto key = std::make_pair(static_cast<u32>(format), static_cast<u32>(palette_format));
auto iter = s_texture_decoding_program_info.find(key);
if (iter == s_texture_decoding_program_info.end())
return false;
#ifdef TIME_TEXTURE_DECODING
GPUTimer timer;
#endif
// Copy to GPU-visible buffer, aligned to the data type.
auto info = iter->second;
u32 bytes_per_buffer_elem =
TextureConversionShader::GetBytesPerBufferElement(info.base_info->buffer_format);
// Only copy palette if it is required.
bool has_palette = info.base_info->palette_size > 0;
u32 total_upload_size = static_cast<u32>(data_size);
u32 palette_offset = total_upload_size;
if (has_palette)
{
// Align to u16.
if ((total_upload_size % sizeof(u16)) != 0)
{
total_upload_size++;
palette_offset++;
}
total_upload_size += info.base_info->palette_size;
}
// Allocate space in stream buffer, and copy texture + palette across.
u32 offset = s_palette_stream_buffer->Stream(data_size, data);
if (has_palette)
s_palette_stream_buffer->Stream(info.base_info->palette_size, sizeof(u16), palette);
info.program.Bind();
// Calculate stride in buffer elements
u32 row_stride_in_elements = row_stride / bytes_per_buffer_elem;
u32 offset_in_elements = offset / bytes_per_buffer_elem;
u32 palette_offset_in_elements = (offset + palette_offset) / sizeof(u16);
if (info.uniform_dst_size >= 0)
glUniform2ui(info.uniform_dst_size, width, height);
if (info.uniform_src_size >= 0)
glUniform2ui(info.uniform_src_size, aligned_width, aligned_height);
if (info.uniform_src_offset >= 0)
glUniform1ui(info.uniform_src_offset, offset_in_elements);
if (info.uniform_src_row_stride >= 0)
glUniform1ui(info.uniform_src_row_stride, row_stride_in_elements);
if (info.uniform_palette_offset >= 0)
glUniform1ui(info.uniform_palette_offset, palette_offset_in_elements);
glActiveTexture(GL_TEXTURE9);
glBindTexture(GL_TEXTURE_BUFFER, s_texture_decoding_buffer_views[info.base_info->buffer_format]);
if (has_palette)
{
// Use an R16UI view for the palette.
glActiveTexture(GL_TEXTURE10);
glBindTexture(GL_TEXTURE_BUFFER, s_palette_resolv_texture);
}
auto dispatch_groups =
TextureConversionShader::GetDispatchCount(info.base_info, aligned_width, aligned_height);
glBindImageTexture(0, texture, dst_level, GL_TRUE, 0,
GL_WRITE_ONLY, GL_RGBA8);
glDispatchCompute(dispatch_groups.first, dispatch_groups.second, 1);
glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
TextureCache::SetStage();
#ifdef TIME_TEXTURE_DECODING
WARN_LOG(VIDEO, "Decode texture format %u size %ux%u took %.4fms", static_cast<u32>(format),
width, height, timer.GetTimeMilliseconds());
#endif
return true;
}
}

View File

@@ -33,6 +33,7 @@ private:
int gl_format;
int gl_iformat;
int gl_siformat;
int gl_type;
void SetFormat();
//TexMode0 mode; // current filter and clamp modes that texture is set to
@@ -49,13 +50,13 @@ private:
void Load(const u8* src, u32 width, u32 height,
u32 expanded_width, u32 level) override;
void LoadMaterialMap(const u8* src, u32 width, u32 height, u32 level) override;
void Load(const u8* src, u32 width, u32 height, u32 expandedWidth,
u32 expandedHeight, const s32 texformat, const u32 tlutaddr, const TlutFormat tlutfmt, u32 level) override;
void LoadFromTmem(const u8* ar_src, const u8* gb_src, u32 width, u32 height,
u32 expanded_width, u32 expanded_Height, u32 level) override;
void FromRenderTarget(bool is_depth_copy, const EFBRectangle& srcRect,
bool scaleByHalf, unsigned int cbufid, const float *colmat, u32 width, u32 height) override;
bool DecodeTextureOnGPU(u32 dst_level, const u8* data,
u32 data_size, TextureFormat format, u32 width, u32 height,
u32 aligned_width, u32 aligned_height, u32 row_stride,
const u8* palette, TlutFormat palette_format) override;
bool SupportsMaterialMap() const override
{
return nrm_texture != 0;
@@ -72,13 +73,14 @@ private:
TCacheEntryBase* CreateTexture(const TCacheEntryConfig& config) override;
void CopyEFB(u8* dst, u32 format, u32 native_width, u32 bytes_per_row, u32 num_blocks_y, u32 memory_stride,
bool is_depth_copy, const EFBRectangle& srcRect,
bool isIntensity, bool scaleByHalf) override;
void CopyEFB(u8* dst, const EFBCopyFormat& format, u32 native_width, u32 bytes_per_row,
u32 num_blocks_y, u32 memory_stride, bool is_depth_copy,
const EFBRectangle& src_rect, bool scale_by_half) override;
bool Palettize(TCacheEntryBase* entry, const TCacheEntryBase* base_entry) override;
void LoadLut(u32 lutFmt, void* addr, u32 size) override;
bool CompileShaders() override;
void DeleteShaders() override;
bool SupportsGPUTextureDecode(TextureFormat format, TlutFormat palette_format) override;
void* m_last_addr = {};
u32 m_last_size = {};
u64 m_last_hash = {};

View File

@@ -45,10 +45,12 @@ static int s_rgbToYuyvUniform_loc;
static SHADER s_yuyvToRgbProgram;
// Not all slots are taken - but who cares.
const u32 NUM_ENCODING_PROGRAMS = 64;
static SHADER s_encodingPrograms[NUM_ENCODING_PROGRAMS];
static int s_encodingUniforms[NUM_ENCODING_PROGRAMS];
struct EncodingProgram
{
SHADER program;
GLint copy_position_uniform;
};
static std::map<EFBCopyFormat, EncodingProgram> s_encoding_programs;
static GLuint s_PBO = 0; // for readback with different strides
@@ -134,40 +136,37 @@ static void CreatePrograms()
ProgramShaderCache::CompileShader(s_yuyvToRgbProgram, VProgramYuyvToRgb, FProgramYuyvToRgb);
}
static SHADER &GetOrCreateEncodingShader(u32 format)
static EncodingProgram& GetOrCreateEncodingShader(const EFBCopyFormat& format)
{
if (format >= NUM_ENCODING_PROGRAMS)
{
PanicAlert("Unknown texture copy format: 0x%x\n", format);
return s_encodingPrograms[0];
}
auto iter = s_encoding_programs.find(format);
if (iter != s_encoding_programs.end())
return iter->second;
if (s_encodingPrograms[format].glprogid == 0)
{
const char* shader = TextureConversionShader::GenerateEncodingShader(format, API_OPENGL);
const char* shader = TextureConversionShader::GenerateEncodingShader(format, API_TYPE::API_OPENGL);
#if defined(_DEBUG) || defined(DEBUGFAST)
if (g_ActiveConfig.iLog & CONF_SAVESHADERS && shader)
{
static int counter = 0;
std::string filename = StringFromFormat("%senc_%04i.txt", File::GetUserPath(D_DUMP_IDX).c_str(), counter++);
if (g_ActiveConfig.iLog & CONF_SAVESHADERS && shader)
{
static int counter = 0;
std::string filename =
StringFromFormat("%senc_%04i.txt", File::GetUserPath(D_DUMP_IDX).c_str(), counter++);
SaveData(filename, shader);
}
SaveData(filename, shader);
}
#endif
const char *VProgram =
"void main()\n"
"{\n"
" vec2 rawpos = vec2(gl_VertexID&1, gl_VertexID&2);\n"
" gl_Position = vec4(rawpos*2.0-1.0, 0.0, 1.0);\n"
"}\n";
const char* VProgram = "void main()\n"
"{\n"
" vec2 rawpos = vec2(gl_VertexID&1, gl_VertexID&2);\n"
" gl_Position = vec4(rawpos*2.0-1.0, 0.0, 1.0);\n"
"}\n";
ProgramShaderCache::CompileShader(s_encodingPrograms[format], VProgram, shader);
EncodingProgram program;
if (!ProgramShaderCache::CompileShader(program.program, VProgram, shader))
PanicAlert("Failed to compile texture encoding shader.");
s_encodingUniforms[format] = glGetUniformLocation(s_encodingPrograms[format].glprogid, "position");
}
return s_encodingPrograms[format];
program.copy_position_uniform = glGetUniformLocation(program.program.glprogid, "position");
return s_encoding_programs.emplace(format, program).first->second;
}
void Init()
@@ -206,8 +205,9 @@ void Shutdown()
s_rgbToYuyvProgram.Destroy();
s_yuyvToRgbProgram.Destroy();
for (auto& program : s_encodingPrograms)
program.Destroy();
for (auto& program : s_encoding_programs)
program.second.program.Destroy();
s_encoding_programs.clear();
s_srcTexture = 0;
s_dstTexture = 0;
@@ -267,24 +267,25 @@ static void EncodeToRamUsingShader(GLuint srcTexture,
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
}
void EncodeToRamFromTexture(u8* dest_ptr, u32 format, u32 native_width, u32 bytes_per_row, u32 num_blocks_y, u32 memory_stride,
bool is_depth_copy, bool bIsIntensityFmt, bool bScaleByHalf, const EFBRectangle& source)
void EncodeToRamFromTexture(u8* dest_ptr, const EFBCopyFormat& format, u32 native_width,
u32 bytes_per_row, u32 num_blocks_y, u32 memory_stride,
bool is_depth_copy, const EFBRectangle& src_rect, bool scale_by_half)
{
g_renderer->ResetAPIState();
SHADER& texconv_shader = GetOrCreateEncodingShader(format);
EncodingProgram& texconv_shader = GetOrCreateEncodingShader(format);
texconv_shader.Bind();
glUniform4i(s_encodingUniforms[format],
source.left, source.top, native_width, bScaleByHalf ? 2 : 1);
texconv_shader.program.Bind();
glUniform4i(texconv_shader.copy_position_uniform, src_rect.left, src_rect.top, native_width,
scale_by_half ? 2 : 1);
const GLuint read_texture = is_depth_copy ?
FramebufferManager::ResolveAndGetDepthTarget(source) :
FramebufferManager::ResolveAndGetRenderTarget(source);
FramebufferManager::ResolveAndGetDepthTarget(src_rect) :
FramebufferManager::ResolveAndGetRenderTarget(src_rect);
EncodeToRamUsingShader(read_texture,
dest_ptr, bytes_per_row, num_blocks_y,
memory_stride, bScaleByHalf && !is_depth_copy);
memory_stride, scale_by_half && !is_depth_copy);
FramebufferManager::SetFramebuffer(0);
g_renderer->RestoreAPIState();

View File

@@ -5,7 +5,9 @@
#pragma once
#include "Common/GL/GLUtil.h"
#include "VideoCommon/TextureCacheBase.h"
#include "VideoCommon/TextureDecoder.h"
#include "VideoCommon/VideoCommon.h"
namespace OGL
@@ -24,8 +26,9 @@ void EncodeToRamYUYV(GLuint srcTexture, const TargetRectangle& sourceRc,
void DecodeToTexture(u32 xfbAddr, int srcWidth, int srcHeight, GLuint destTexture);
void EncodeToRamFromTexture(u8* dest_ptr, u32 format, u32 native_width, u32 bytes_per_row, u32 num_blocks_y, u32 memory_stride,
bool is_depth_copy, bool bIsIntensityFmt, bool bScaleByHalf, const EFBRectangle& source);
void EncodeToRamFromTexture(u8* dest_ptr, const EFBCopyFormat& format, u32 native_width,
u32 bytes_per_row, u32 num_blocks_y, u32 memory_stride,
bool is_depth_copy, const EFBRectangle& src_rect, bool scale_by_half);
}

View File

@@ -30,11 +30,7 @@ namespace OGL
const u32 MAX_IBUFFER_SIZE = 2 * 1024 * 1024;
const u32 MAX_VBUFFER_SIZE = 32 * 1024 * 1024;
static std::unique_ptr<StreamBuffer> s_vertexBuffer;
static std::unique_ptr<StreamBuffer> s_indexBuffer;
static size_t s_baseVertex;
static size_t s_index_offset;
static u16* s_index_buffer_base;
VertexManager::VertexManager() : m_cpu_v_buffer(MAXVBUFFERSIZE), m_cpu_i_buffer(MAXIBUFFERSIZE)
{
CreateDeviceObjects();
@@ -47,36 +43,36 @@ VertexManager::~VertexManager()
void VertexManager::CreateDeviceObjects()
{
s_vertexBuffer = StreamBuffer::Create(GL_ARRAY_BUFFER, MAX_VBUFFER_SIZE);
m_vertex_buffers = s_vertexBuffer->m_buffer;
m_vertexBuffer = StreamBuffer::Create(GL_ARRAY_BUFFER, MAX_VBUFFER_SIZE);
m_vertex_buffers = m_vertexBuffer->m_buffer;
s_indexBuffer = StreamBuffer::Create(GL_ELEMENT_ARRAY_BUFFER, MAX_IBUFFER_SIZE);
m_index_buffers = s_indexBuffer->m_buffer;
m_indexBuffer = StreamBuffer::Create(GL_ELEMENT_ARRAY_BUFFER, MAX_IBUFFER_SIZE);
m_index_buffers = m_indexBuffer->m_buffer;
m_last_vao = 0;
}
void VertexManager::DestroyDeviceObjects()
{
s_vertexBuffer.reset();
s_indexBuffer.reset();
m_vertexBuffer.reset();
m_indexBuffer.reset();
}
void VertexManager::PrepareDrawBuffers(u32 stride)
{
u32 vertex_data_size = IndexGenerator::GetNumVerts() * stride;
u32 index_data_size = IndexGenerator::GetIndexLen() * sizeof(u16);
s_baseVertex = s_vertexBuffer->Stream(vertex_data_size, stride, m_cpu_v_buffer.data()) / stride;
s_index_offset = s_indexBuffer->Stream(index_data_size, m_cpu_i_buffer.data());
m_baseVertex = m_vertexBuffer->Stream(vertex_data_size, stride, m_cpu_v_buffer.data()) / stride;
m_index_offset = m_indexBuffer->Stream(index_data_size, m_cpu_i_buffer.data());
ADDSTAT(stats.thisFrame.bytesVertexStreamed, vertex_data_size);
ADDSTAT(stats.thisFrame.bytesIndexStreamed, index_data_size);
}
void VertexManager::ResetBuffer(u32 stride)
{
s_pCurBufferPointer = s_pBaseBufferPointer = m_cpu_v_buffer.data();
s_pEndBufferPointer = s_pBaseBufferPointer + m_cpu_v_buffer.size();
s_index_buffer_base = m_cpu_i_buffer.data();
m_pCurBufferPointer = m_pBaseBufferPointer = m_cpu_v_buffer.data();
m_pEndBufferPointer = m_pBaseBufferPointer + m_cpu_v_buffer.size();
m_index_buffer_base = m_cpu_i_buffer.data();
IndexGenerator::Start(m_cpu_i_buffer.data());
}
@@ -86,24 +82,24 @@ void VertexManager::Draw(u32 stride)
u32 max_index = IndexGenerator::GetNumVerts();
GLenum primitive_mode = 0;
static const GLenum modes[3] = {
GL_POINTS,
GL_POINTS,
GL_LINES,
GL_TRIANGLES
};
primitive_mode = modes[current_primitive_type];
primitive_mode = modes[m_current_primitive_type];
bool cull_changed = primitive_mode != GL_TRIANGLES && bpmem.genMode.cullmode > 0;
if(cull_changed)
if (cull_changed)
{
glDisable(GL_CULL_FACE);
}
if (g_ogl_config.bSupportsGLBaseVertex)
{
glDrawRangeElementsBaseVertex(primitive_mode, 0, max_index, index_size, GL_UNSIGNED_SHORT, (u8*)nullptr + s_index_offset, (GLint)s_baseVertex);
glDrawRangeElementsBaseVertex(primitive_mode, 0, max_index, index_size, GL_UNSIGNED_SHORT, (u8*)nullptr + m_index_offset, (GLint)m_baseVertex);
}
else
{
glDrawRangeElements(primitive_mode, 0, max_index, index_size, GL_UNSIGNED_SHORT, (u8*)nullptr + s_index_offset);
glDrawRangeElements(primitive_mode, 0, max_index, index_size, GL_UNSIGNED_SHORT, (u8*)nullptr + m_index_offset);
}
INCSTAT(stats.thisFrame.numDrawCalls);
@@ -122,21 +118,21 @@ void VertexManager::PrepareShaders(PrimitiveType primitive, u32 components, cons
// the same pass as regular rendering.
if (useDstAlpha && dualSourcePossible)
{
ProgramShaderCache::SetShader(PSRM_DUAL_SOURCE_BLEND, VertexLoaderManager::g_current_components, current_primitive_type);
ProgramShaderCache::SetShader(PSRM_DUAL_SOURCE_BLEND, VertexLoaderManager::g_current_components, m_current_primitive_type);
}
else
{
if (useDstAlpha)
{
ProgramShaderCache::SetShader(PSRM_ALPHA_PASS, VertexLoaderManager::g_current_components, current_primitive_type);
ProgramShaderCache::SetShader(PSRM_ALPHA_PASS, VertexLoaderManager::g_current_components, m_current_primitive_type);
}
ProgramShaderCache::SetShader(PSRM_DEFAULT, VertexLoaderManager::g_current_components, current_primitive_type);
ProgramShaderCache::SetShader(PSRM_DEFAULT, VertexLoaderManager::g_current_components, m_current_primitive_type);
}
}
u16* VertexManager::GetIndexBuffer()
{
return s_index_buffer_base;
return m_index_buffer_base;
}
void VertexManager::vFlush(bool useDstAlpha)
{
@@ -162,11 +158,11 @@ void VertexManager::vFlush(bool useDstAlpha)
OGL::SHADER* active_shader = nullptr;
if (useDstAlpha && dualSourcePossible)
{
active_shader = ProgramShaderCache::SetShader(PSRM_DUAL_SOURCE_BLEND, VertexLoaderManager::g_current_components, current_primitive_type);
active_shader = ProgramShaderCache::SetShader(PSRM_DUAL_SOURCE_BLEND, VertexLoaderManager::g_current_components, m_current_primitive_type);
}
else
{
active_shader = ProgramShaderCache::SetShader(PSRM_DEFAULT, VertexLoaderManager::g_current_components, current_primitive_type);
active_shader = ProgramShaderCache::SetShader(PSRM_DEFAULT, VertexLoaderManager::g_current_components, m_current_primitive_type);
}
active_shader->Bind();
g_renderer->ApplyState(false);
@@ -181,7 +177,7 @@ void VertexManager::vFlush(bool useDstAlpha)
// run through vertex groups again to set alpha
if (useDstAlpha && (!dualSourcePossible || logic_op_enabled))
{
active_shader = ProgramShaderCache::SetShader(PSRM_ALPHA_PASS, VertexLoaderManager::g_current_components, current_primitive_type);
active_shader = ProgramShaderCache::SetShader(PSRM_ALPHA_PASS, VertexLoaderManager::g_current_components, m_current_primitive_type);
// only update alpha
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE);
@@ -189,7 +185,7 @@ void VertexManager::vFlush(bool useDstAlpha)
glDisable(GL_BLEND);
if (logic_op_enabled)
glDisable(GL_COLOR_LOGIC_OP);
active_shader->Bind();
Draw(stride);

View File

@@ -7,6 +7,8 @@
#include "VideoCommon/NativeVertexFormat.h"
#include "VideoCommon/VertexManagerBase.h"
class StreamBuffer;
namespace OGL
{
class GLVertexFormat : public NativeVertexFormat
@@ -47,5 +49,10 @@ private:
// Alternative buffers in CPU memory for primatives we are going to discard.
std::vector<u8, Common::aligned_allocator<u8, 16>> m_cpu_v_buffer;
std::vector<u16, Common::aligned_allocator<u16, 16>> m_cpu_i_buffer;
std::unique_ptr<StreamBuffer> m_vertexBuffer;
std::unique_ptr<StreamBuffer> m_indexBuffer;
size_t m_baseVertex;
size_t m_index_offset;
u16* m_index_buffer_base;
};
}

View File

@@ -95,7 +95,7 @@ void VideoBackend::InitBackendInfo()
g_Config.backend_info.APIType = API_OPENGL;
g_Config.backend_info.MaxTextureSize = 1024;
#ifdef _WIN32
g_Config.backend_info.bSupportedFormats[PC_TEX_FMT_BGRA32] = true;
g_Config.backend_info.bSupportedFormats[PC_TEX_FMT_BGRA32] = false;
g_Config.backend_info.bSupportedFormats[PC_TEX_FMT_RGBA32] = true;
g_Config.backend_info.bSupportedFormats[PC_TEX_FMT_I4_AS_I8] = false;
g_Config.backend_info.bSupportedFormats[PC_TEX_FMT_IA4_AS_IA8] = false;
@@ -116,7 +116,8 @@ void VideoBackend::InitBackendInfo()
g_Config.backend_info.bSupportsPixelLighting = true;
g_Config.backend_info.bSupportsNormalMaps = true;
g_Config.backend_info.bSupportsTessellation = false;
g_Config.backend_info.bSupportsComputeTextureDecoding = false;
g_Config.backend_info.bSupportsComputeShaders = false;
g_Config.backend_info.bSupportsGPUTextureDecoding = true;
g_Config.backend_info.bSupportsComputeTextureEncoding = false;
g_Config.backend_info.bSupportsDepthClamp = true;
g_Config.backend_info.bSupportsMultithreading = false;
@@ -159,7 +160,7 @@ void VideoBackend::Video_Prepare()
ProgramShaderCache::Init();
g_texture_cache = std::make_unique<TextureCache>();
g_sampler_cache = std::make_unique<SamplerCache>();
Renderer::Init();
g_renderer->Init();
TextureConverter::Init();
BBox::Init();
}
@@ -176,7 +177,7 @@ void VideoBackend::Video_Cleanup()
// The following calls are NOT Thread Safe
// And need to be called from the video thread
CleanupShared();
Renderer::Shutdown();
static_cast<Renderer*>(g_renderer.get())->Shutdown();
BBox::Shutdown();
TextureConverter::Shutdown();
g_sampler_cache.reset();

View File

@@ -16,8 +16,8 @@ class SWRenderer: public Renderer
public:
~SWRenderer() override;
static void Init();
static void Shutdown();
void Init() override;
void Shutdown() override;
static u8* GetNextColorTexture();
static u8* GetCurrentColorTexture();

View File

@@ -56,8 +56,8 @@ SWVertexLoader::~SWVertexLoader()
void SWVertexLoader::ResetBuffer(u32 stride)
{
s_pCurBufferPointer = s_pBaseBufferPointer = LocalVBuffer.data();
s_pEndBufferPointer = s_pCurBufferPointer + LocalVBuffer.size();
m_pCurBufferPointer = m_pBaseBufferPointer = LocalVBuffer.data();
m_pEndBufferPointer = m_pCurBufferPointer + LocalVBuffer.size();
IndexGenerator::Start(GetIndexBuffer());
}
@@ -66,7 +66,7 @@ void SWVertexLoader::vFlush(bool useDstAlpha)
DebugUtil::OnObjectBegin();
u8 primitiveType = 0;
switch (current_primitive_type)
switch (m_current_primitive_type)
{
case PRIMITIVE_POINTS:
primitiveType = GX_DRAW_POINTS;

View File

@@ -87,9 +87,9 @@ public:
{
return false;
}
void CopyEFB(u8* dst, u32 format, u32 native_width, u32 bytes_per_row, u32 num_blocks_y, u32 memory_stride,
bool is_depth_copy, const EFBRectangle& srcRect,
bool isIntensity, bool scaleByHalf) override
void CopyEFB(u8* dst, const EFBCopyFormat& format, u32 native_width, u32 bytes_per_row,
u32 num_blocks_y, u32 memory_stride, bool is_depth_copy,
const EFBRectangle& src_rect, bool scale_by_half) override
{
EfbCopy::CopyEfb();
}
@@ -107,14 +107,6 @@ private:
void Load(const u8* src, u32 width, u32 height,
u32 expanded_width, u32 level) override
{}
void LoadMaterialMap(const u8* src, u32 width, u32 height, u32 level) override
{}
void Load(const u8* src, u32 width, u32 height, u32 expandedWidth,
u32 expandedHeight, const s32 texformat, const u32 tlutaddr, const TlutFormat tlutfmt, u32 level) override
{}
void LoadFromTmem(const u8* ar_src, const u8* gb_src, u32 width, u32 height,
u32 expanded_width, u32 expanded_Height, u32 level) override
{}
bool SupportsMaterialMap() const override
{
return false;
@@ -212,7 +204,7 @@ bool VideoSoftware::Initialize(void *window_handle)
PixelEngine::Init();
Clipper::Init();
Rasterizer::Init();
SWRenderer::Init();
g_renderer->Init();
DebugUtil::Init();
// Do our OSD callbacks
@@ -238,11 +230,11 @@ void VideoSoftware::Video_Cleanup()
if (g_renderer)
{
Fifo::Shutdown();
SWRenderer::Shutdown();
g_renderer->Shutdown();
DebugUtil::Shutdown();
// The following calls are NOT Thread Safe
// And need to be called from the video thread
SWRenderer::Shutdown();
g_renderer->Shutdown();
VertexLoaderManager::Shutdown();
g_framebuffer_manager.reset();
g_texture_cache.reset();
@@ -269,7 +261,7 @@ void VideoSoftware::Video_Prepare()
VertexShaderManager::Init();
PixelShaderManager::Init(true);
g_texture_cache = std::make_unique<TextureCache>();
SWRenderer::Init();
g_renderer->Init();
VertexLoaderManager::Init();
g_framebuffer_manager = std::make_unique<FramebufferManager>();

View File

@@ -37,5 +37,5 @@ include_directories(SYSTEM ${CMAKE_SOURCE_DIR}/Externals/glslang/SPIRV)
# Link against glslang, the other necessary libraries are referenced by the executable.
add_dolphin_library(videovulkan "${SRCS}" "${LIBS}")
target_link_libraries(videovulkan glslang)
target_link_libraries(videovulkan PRIVATE glslang)

View File

@@ -91,7 +91,8 @@ bool CommandBufferManager::CreateCommandBuffers()
VkDescriptorPoolSize pool_sizes[] = { { VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 500000 },
{ VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 500000 },
{ VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 16 },
{ VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, 1024 } };
{ VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, 16384 },
{ VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 16384 } };
VkDescriptorPoolCreateInfo pool_create_info = { VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
nullptr,

View File

@@ -30,6 +30,7 @@ enum DESCRIPTOR_SET_LAYOUT
DESCRIPTOR_SET_LAYOUT_PIXEL_SHADER_SAMPLERS,
DESCRIPTOR_SET_LAYOUT_SHADER_STORAGE_BUFFERS,
DESCRIPTOR_SET_LAYOUT_TEXEL_BUFFERS,
DESCRIPTOR_SET_LAYOUT_COMPUTE,
NUM_DESCRIPTOR_SET_LAYOUTS
};
@@ -52,6 +53,12 @@ enum DESCRIPTOR_SET_BIND_POINT
// - Same as standard, plus 128 bytes of push constants, accessible from all stages.
// - Texture Decoding
// - Same as push constant, plus a single texel buffer accessible from PS.
// - Compute
// - 1 uniform buffer [set=0, binding=0]
// - 4 combined image samplers [set=0, binding=1-4]
// - 1 texel buffer [set=0, binding=5]
// - 1 storage image [set=0, binding=6]
// - 128 bytes of push constants
//
// All four pipeline layout share the first two descriptor sets (uniform buffers, PS samplers).
// The third descriptor set (see bind points above) is used for storage or texel buffers.
@@ -62,6 +69,7 @@ enum PIPELINE_LAYOUT
PIPELINE_LAYOUT_BBOX,
PIPELINE_LAYOUT_PUSH_CONSTANT,
PIPELINE_LAYOUT_TEXTURE_CONVERSION,
PIPELINE_LAYOUT_COMPUTE,
NUM_PIPELINE_LAYOUTS
};
@@ -101,7 +109,7 @@ constexpr size_t MAXIMUM_TEXTURE_UPLOAD_BUFFER_SIZE = 64 * 1024 * 1024;
// streaming buffer and be blocking frequently. Games are unlikely to have textures this
// large anyway, so it's only really an issue for HD texture packs, and memory is not
// a limiting factor in these scenarios anyway.
constexpr size_t STAGING_TEXTURE_UPLOAD_THRESHOLD = 1024 * 1024 * 4;
constexpr size_t STAGING_TEXTURE_UPLOAD_THRESHOLD = 1024 * 1024 * 8;
// Streaming uniform buffer size
constexpr size_t INITIAL_UNIFORM_STREAM_BUFFER_SIZE = 16 * 1024 * 1024;

View File

@@ -225,8 +225,8 @@ void FramebufferManager::DestroyEFBRenderPass()
bool FramebufferManager::CreateEFBFramebuffer()
{
m_efb_width = static_cast<u32>(std::max(Renderer::GetTargetWidth(), 1));
m_efb_height = static_cast<u32>(std::max(Renderer::GetTargetHeight(), 1));
m_efb_width = static_cast<u32>(std::max(g_renderer->GetTargetWidth(), 1));
m_efb_height = static_cast<u32>(std::max(g_renderer->GetTargetHeight(), 1));
m_efb_layers = (g_ActiveConfig.iStereoMode != STEREO_OFF) ? 2 : 1;
INFO_LOG(VIDEO, "EFB size: %ux%ux%u", m_efb_width, m_efb_height, m_efb_layers);
@@ -461,6 +461,12 @@ Texture2D* FramebufferManager::ResolveEFBColorTexture(const VkRect2D& region)
// Can't resolve within a render pass.
StateTracker::GetInstance()->EndRenderPass();
// It's not valid to resolve out-of-bounds coordinates.
// Ensuring the region is within the image is the caller's responsibility.
_assert_(region.offset.x >= 0 && region.offset.y >= 0 &&
(static_cast<u32>(region.offset.x) + region.extent.width) <= m_efb_width &&
(static_cast<u32>(region.offset.y) + region.extent.height) <= m_efb_height);
// Resolving is considered to be a transfer operation.
m_efb_color_texture->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(),
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);

View File

@@ -66,6 +66,9 @@ public:
Texture2D* ResolveEFBColorTexture(const VkRect2D& region);
Texture2D* ResolveEFBDepthTexture(const VkRect2D& region);
// Returns the texture that the EFB color texture is resolved to when multisampling is enabled.
// Ensure ResolveEFBColorTexture is called before this method.
Texture2D* GetResolvedEFBColorTexture() const { return m_efb_resolve_color_texture.get(); }
// Reads a framebuffer value back from the GPU. This may block if the cache is not current.
u32 PeekEFBColor(u32 x, u32 y);
float PeekEFBDepth(u32 x, u32 y);

View File

@@ -312,6 +312,58 @@ std::pair<VkPipeline, bool> ObjectCache::GetPipelineWithCacheResult(const Pipeli
return{ pipeline, false };
}
VkPipeline ObjectCache::CreateComputePipeline(const ComputePipelineInfo& info)
{
VkComputePipelineCreateInfo pipeline_info = { VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
nullptr,
0,
{ VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
nullptr, 0, VK_SHADER_STAGE_COMPUTE_BIT, info.cs,
"main", nullptr },
info.pipeline_layout,
VK_NULL_HANDLE,
-1 };
VkPipeline pipeline;
VkResult res = vkCreateComputePipelines(g_vulkan_context->GetDevice(), VK_NULL_HANDLE, 1,
&pipeline_info, nullptr, &pipeline);
if (res != VK_SUCCESS)
{
LOG_VULKAN_ERROR(res, "vkCreateComputePipelines failed: ");
return VK_NULL_HANDLE;
}
return pipeline;
}
VkPipeline ObjectCache::GetComputePipeline(const ComputePipelineInfo& info)
{
auto iter = m_compute_pipeline_objects.find(info);
if (iter != m_compute_pipeline_objects.end())
return iter->second;
VkPipeline pipeline = CreateComputePipeline(info);
m_compute_pipeline_objects.emplace(info, pipeline);
return pipeline;
}
void ObjectCache::ClearPipelineCache()
{
for (const auto& it : m_pipeline_objects)
{
if (it.second != VK_NULL_HANDLE)
vkDestroyPipeline(g_vulkan_context->GetDevice(), it.second, nullptr);
}
m_pipeline_objects.clear();
for (const auto& it : m_compute_pipeline_objects)
{
if (it.second != VK_NULL_HANDLE)
vkDestroyPipeline(g_vulkan_context->GetDevice(), it.second, nullptr);
}
m_compute_pipeline_objects.clear();
}
std::string ObjectCache::GetDiskCacheFileName(const char* type)
{
return StringFromFormat("%sIVK-%s-%s.cache", File::GetUserPath(D_SHADERCACHE_IDX).c_str(),
@@ -464,12 +516,7 @@ bool ObjectCache::ValidatePipelineCache(const u8* data, size_t data_length)
void ObjectCache::DestroyPipelineCache()
{
for (const auto& it : m_pipeline_objects)
{
if (it.second != VK_NULL_HANDLE)
vkDestroyPipeline(g_vulkan_context->GetDevice(), it.second, nullptr);
}
m_pipeline_objects.clear();
ClearPipelineCache();
vkDestroyPipelineCache(g_vulkan_context->GetDevice(), m_pipeline_cache, nullptr);
m_pipeline_cache = VK_NULL_HANDLE;
@@ -828,6 +875,17 @@ bool ObjectCache::CreateDescriptorSetLayouts()
{0, VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT},
};
static const VkDescriptorSetLayoutBinding compute_set_bindings[] = {
{ 0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1, VK_SHADER_STAGE_COMPUTE_BIT },
{ 1, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_COMPUTE_BIT },
{ 2, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_COMPUTE_BIT },
{ 3, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_COMPUTE_BIT },
{ 4, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_COMPUTE_BIT },
{ 5, VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, 1, VK_SHADER_STAGE_COMPUTE_BIT },
{ 6, VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, 1, VK_SHADER_STAGE_COMPUTE_BIT },
{ 7, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1, VK_SHADER_STAGE_COMPUTE_BIT },
};
static const VkDescriptorSetLayoutCreateInfo create_infos[NUM_DESCRIPTOR_SET_LAYOUTS] = {
{VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, nullptr, 0,
static_cast<u32>(ArraySize(ubo_set_bindings)), ubo_set_bindings},
@@ -836,7 +894,9 @@ bool ObjectCache::CreateDescriptorSetLayouts()
{VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, nullptr, 0,
static_cast<u32>(ArraySize(ssbo_set_bindings)), ssbo_set_bindings},
{VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, nullptr, 0,
static_cast<u32>(ArraySize(texel_buffer_set_bindings)), texel_buffer_set_bindings} };
static_cast<u32>(ArraySize(texel_buffer_set_bindings)), texel_buffer_set_bindings},
{ VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, nullptr, 0,
static_cast<u32>(ArraySize(compute_set_bindings)), compute_set_bindings } };
for (size_t i = 0; i < NUM_DESCRIPTOR_SET_LAYOUTS; i++)
{
@@ -877,8 +937,11 @@ bool ObjectCache::CreatePipelineLayouts()
m_descriptor_set_layouts[DESCRIPTOR_SET_LAYOUT_UNIFORM_BUFFERS],
m_descriptor_set_layouts[DESCRIPTOR_SET_LAYOUT_PIXEL_SHADER_SAMPLERS],
m_descriptor_set_layouts[DESCRIPTOR_SET_LAYOUT_TEXEL_BUFFERS] };
VkDescriptorSetLayout compute_sets[] = { m_descriptor_set_layouts[DESCRIPTOR_SET_LAYOUT_COMPUTE] };
VkPushConstantRange push_constant_range = {
VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0, PUSH_CONSTANT_BUFFER_SIZE };
VkPushConstantRange compute_push_constant_range = { VK_SHADER_STAGE_COMPUTE_BIT, 0,
PUSH_CONSTANT_BUFFER_SIZE };
// Info for each pipeline layout
VkPipelineLayoutCreateInfo pipeline_layout_info[NUM_PIPELINE_LAYOUTS] = {
@@ -897,7 +960,11 @@ bool ObjectCache::CreatePipelineLayouts()
// Texture Conversion
{ VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, nullptr, 0,
static_cast<u32>(ArraySize(texture_conversion_sets)), texture_conversion_sets, 1,
&push_constant_range } };
&push_constant_range },
// Compute
{ VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, nullptr, 0,
static_cast<u32>(ArraySize(compute_sets)), compute_sets, 1, &compute_push_constant_range } };
for (size_t i = 0; i < NUM_PIPELINE_LAYOUTS; i++)
{

View File

@@ -79,6 +79,42 @@ struct PipelineInfoHash
}
};
struct ComputePipelineInfo
{
VkPipelineLayout pipeline_layout;
VkShaderModule cs;
bool operator==(const ComputePipelineInfo& rhs) const
{
return std::memcmp(this, &rhs, sizeof(rhs)) == 0;
}
bool operator!=(const ComputePipelineInfo& rhs) const
{
return !operator==(rhs);
}
bool operator<(const ComputePipelineInfo& rhs) const
{
return std::memcmp(this, &rhs, sizeof(rhs)) < 0;
}
bool operator>(const ComputePipelineInfo& rhs) const
{
return std::memcmp(this, &rhs, sizeof(rhs)) > 0;
}
};
struct ComputePipelineInfoHash
{
std::size_t operator()(const ComputePipelineInfo& key) const
{
size_t h = -1;
h = h * 137 + (uintptr_t)key.pipeline_layout;
h = h * 137 + (uintptr_t)key.cs;
return h;
}
};
class ObjectCache
{
public:
@@ -137,6 +173,19 @@ public:
// otherwise for a cache hit it will be true.
std::pair<VkPipeline, bool> GetPipelineWithCacheResult(const PipelineInfo& info);
// Creates a compute pipeline, and does not track the handle.
VkPipeline CreateComputePipeline(const ComputePipelineInfo& info);
// Find a pipeline by the specified description, if not found, attempts to create it
VkPipeline GetComputePipeline(const ComputePipelineInfo& info);
// Clears our pipeline cache of all objects. This is necessary when recompiling shaders,
// as drivers are free to return the same pointer again, which means that we may end up using
// and old pipeline object if they are not cleared first. Some stutter may be experienced
// while our cache is rebuilt on use, but the pipeline cache object should mitigate this.
// NOTE: Ensure that none of these objects are in use before calling.
void ClearPipelineCache();
// Saves the pipeline cache to disk. Call when shutting down.
void SavePipelineCache();
@@ -208,6 +257,8 @@ private:
PShaderCache m_ps_cache;
std::unordered_map<PipelineInfo, VkPipeline, PipelineInfoHash> m_pipeline_objects;
std::unordered_map<ComputePipelineInfo, VkPipeline, ComputePipelineInfoHash>
m_compute_pipeline_objects;
VkPipelineCache m_pipeline_cache = VK_NULL_HANDLE;
std::string m_pipeline_cache_filename;

View File

@@ -175,6 +175,11 @@ RasterFont::~RasterFont()
vkDestroyShaderModule(g_vulkan_context->GetDevice(), m_fragment_shader, nullptr);
}
const Texture2D* RasterFont::GetTexture() const
{
return m_texture.get();
}
bool RasterFont::Initialize()
{
// Create shaders and texture
@@ -205,7 +210,7 @@ bool RasterFont::CreateTexture()
m_texture = Texture2D::Create(CHARACTER_WIDTH * CHARACTER_COUNT, CHARACTER_HEIGHT, 1, 1,
VK_FORMAT_R8G8B8A8_UNORM, VK_SAMPLE_COUNT_1_BIT,
VK_IMAGE_VIEW_TYPE_2D, VK_IMAGE_TILING_OPTIMAL,
VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT);
VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_NULL_HANDLE);
if (!m_texture)
return false;

View File

@@ -21,6 +21,8 @@ public:
RasterFont();
~RasterFont();
const Texture2D* GetTexture() const;
bool Initialize();
void PrintMultiLineText(VkRenderPass render_pass, const std::string& text, float start_x,

View File

@@ -8,6 +8,7 @@
#include <cstdio>
#include <limits>
#include <string>
#include <tuple>
#include "Common/Logging/Log.h"
#include "Common/MsgHandler.h"
@@ -38,7 +39,8 @@
namespace Vulkan
{
Renderer::Renderer(std::unique_ptr<SwapChain> swap_chain) : m_swap_chain(std::move(swap_chain))
Renderer::Renderer(std::unique_ptr<SwapChain> swap_chain)
: m_swap_chain(std::move(swap_chain))
{
g_Config.bRunning = true;
UpdateActiveConfig();
@@ -47,16 +49,15 @@ Renderer::Renderer(std::unique_ptr<SwapChain> swap_chain) : m_swap_chain(std::mo
for (size_t i = 0; i < m_sampler_states.size(); i++)
m_sampler_states[i].bits = std::numeric_limits<decltype(m_sampler_states[i].bits)>::max();
m_backbuffer_width = m_swap_chain ? m_swap_chain->GetWidth() : MAX_XFB_WIDTH;
m_backbuffer_height = m_swap_chain ? m_swap_chain->GetHeight() : MAX_XFB_HEIGHT;
// These have to be initialized before FramebufferManager is created.
// If running surfaceless, assume a window size of MAX_XFB_{WIDTH,HEIGHT}.
FramebufferManagerBase::SetLastXfbWidth(MAX_XFB_WIDTH);
FramebufferManagerBase::SetLastXfbHeight(MAX_XFB_HEIGHT);
s_backbuffer_width = m_swap_chain ? m_swap_chain->GetWidth() : MAX_XFB_WIDTH;
s_backbuffer_height = m_swap_chain ? m_swap_chain->GetHeight() : MAX_XFB_HEIGHT;
s_last_efb_scale = g_ActiveConfig.iEFBScale;
UpdateDrawRectangle();
CalculateTargetSize();
PixelShaderManager::SetEfbScaleChanged();
m_last_efb_scale = g_ActiveConfig.iEFBScale;
}
Renderer::~Renderer()
@@ -78,8 +79,17 @@ Renderer* Renderer::GetInstance()
return static_cast<Renderer*>(g_renderer.get());
}
void Renderer::Init()
{
UpdateDrawRectangle();
CalculateTargetSize();
PixelShaderManager::SetEfbScaleChanged();
}
bool Renderer::Initialize()
{
BindEFBToStateTracker();
if (!CreateSemaphores())
@@ -269,12 +279,12 @@ u16 Renderer::BBoxRead(int index)
if (index < 2)
{
// left/right
value = value * EFB_WIDTH / s_target_width;
value = value * EFB_WIDTH / m_target_width;
}
else
{
// up/down
value = value * EFB_HEIGHT / s_target_height;
value = value * EFB_HEIGHT / m_target_height;
}
// fix max values to describe the outer border
@@ -296,12 +306,12 @@ void Renderer::BBoxWrite(int index, u16 value)
if (index < 2)
{
// left/right
scaled_value = scaled_value * s_target_width / EFB_WIDTH;
scaled_value = scaled_value * m_target_width / EFB_WIDTH;
}
else
{
// up/down
scaled_value = scaled_value * s_target_height / EFB_HEIGHT;
scaled_value = scaled_value * m_target_height / EFB_HEIGHT;
}
m_bounding_box->Set(static_cast<size_t>(index), scaled_value);
@@ -334,6 +344,11 @@ void Renderer::ClearScreen(const EFBRectangle& rc, bool color_enable, bool alpha
{
// Native -> EFB coordinates
TargetRectangle target_rc = Renderer::ConvertEFBRectangle(rc);
// Size we pass this size to vkBeginRenderPass, it has to be clamped to the framebuffer
// dimensions. The other backends just silently ignore this case.
target_rc.ClampUL(0, 0, m_target_width, m_target_height);
VkRect2D target_vk_rc = {
{ target_rc.left, target_rc.top },
{ static_cast<uint32_t>(target_rc.GetWidth()), static_cast<uint32_t>(target_rc.GetHeight()) } };
@@ -480,7 +495,7 @@ void Renderer::SwapImpl(u32 xfb_addr, u32 fb_width, u32 fb_stride, u32 fb_height
FramebufferManager::GetInstance()->FlushEFBPokes();
// Check that we actually have an image to render in XFB-on modes.
if ((!XFBWrited && !g_ActiveConfig.RealXFBEnabled()) || !fb_width || !fb_height)
if ((!m_xfb_written && !g_ActiveConfig.RealXFBEnabled()) || !fb_width || !fb_height)
{
Core::Callback_VideoCopiedToXFB(false);
return;
@@ -502,6 +517,15 @@ void Renderer::SwapImpl(u32 xfb_addr, u32 fb_width, u32 fb_stride, u32 fb_height
// are determined by guest state. Currently, the only way to catch these is to update every frame.
UpdateDrawRectangle();
// Scale the source rectangle to the internal resolution when XFB is disabled.
TargetRectangle scaled_efb_rect = Renderer::ConvertEFBRectangle(rc);
// If MSAA is enabled, and we're not using XFB, we need to resolve the EFB framebuffer before
// rendering the final image to the screen, or dumping the frame. This is because we can't resolve
// an image within a render pass, which will have already started by the time it is used.
if (g_ActiveConfig.iMultisamples > 1 && !g_ActiveConfig.bUseXFB)
ResolveEFBForSwap(scaled_efb_rect);
// Render the frame dump image if enabled.
if (IsFrameDumping())
{
@@ -509,7 +533,8 @@ void Renderer::SwapImpl(u32 xfb_addr, u32 fb_width, u32 fb_stride, u32 fb_height
if (!m_frame_dumping_active)
StartFrameDumping();
DrawFrameDump(rc, xfb_addr, xfb_sources, xfb_count, fb_width, fb_stride, fb_height, ticks);
DrawFrameDump(scaled_efb_rect, xfb_addr, xfb_sources, xfb_count, fb_width, fb_stride, fb_height,
ticks);
}
else
{
@@ -526,7 +551,7 @@ void Renderer::SwapImpl(u32 xfb_addr, u32 fb_width, u32 fb_stride, u32 fb_height
// Draw to the screen if we have a swap chain.
if (m_swap_chain)
{
DrawScreen(rc, xfb_addr, xfb_sources, xfb_count, fb_width, fb_stride, fb_height);
DrawScreen(scaled_efb_rect, xfb_addr, xfb_sources, xfb_count, fb_width, fb_stride, fb_height);
// Submit the current command buffer, signaling rendering finished semaphore when it's done
// Because this final command buffer is rendering to the swap chain, we need to wait for
@@ -570,13 +595,25 @@ void Renderer::SwapImpl(u32 xfb_addr, u32 fb_width, u32 fb_stride, u32 fb_height
TextureCache::GetInstance()->Cleanup(frameCount);
}
void Renderer::ResolveEFBForSwap(const TargetRectangle& scaled_rect)
{
// While the source rect can be out-of-range when drawing, the resolve rectangle must be within
// the bounds of the texture.
VkRect2D region = {
{scaled_rect.left, scaled_rect.top},
{static_cast<u32>(scaled_rect.GetWidth()), static_cast<u32>(scaled_rect.GetHeight())} };
region = Util::ClampRect2D(region, FramebufferManager::GetInstance()->GetEFBWidth(),
FramebufferManager::GetInstance()->GetEFBHeight());
FramebufferManager::GetInstance()->ResolveEFBColorTexture(region);
}
void Renderer::DrawFrame(VkRenderPass render_pass, const TargetRectangle& target_rect,
const EFBRectangle& source_rect, u32 xfb_addr,
const TargetRectangle& scaled_efb_rect, u32 xfb_addr,
const XFBSourceBase* const* xfb_sources, u32 xfb_count, u32 fb_width,
u32 fb_stride, u32 fb_height)
{
if (!g_ActiveConfig.bUseXFB)
DrawEFB(render_pass, target_rect, source_rect);
DrawEFB(render_pass, target_rect, scaled_efb_rect);
else if (!g_ActiveConfig.bUseRealXFB)
DrawVirtualXFB(render_pass, target_rect, xfb_addr, xfb_sources, xfb_count, fb_width, fb_stride,
fb_height);
@@ -585,26 +622,18 @@ void Renderer::DrawFrame(VkRenderPass render_pass, const TargetRectangle& target
}
void Renderer::DrawEFB(VkRenderPass render_pass, const TargetRectangle& target_rect,
const EFBRectangle& source_rect)
const TargetRectangle& scaled_efb_rect)
{
// Scale the source rectangle to the selected internal resolution.
TargetRectangle scaled_source_rect = Renderer::ConvertEFBRectangle(source_rect);
scaled_source_rect.left = std::max(scaled_source_rect.left, 0);
scaled_source_rect.right = std::max(scaled_source_rect.right, 0);
scaled_source_rect.top = std::max(scaled_source_rect.top, 0);
scaled_source_rect.bottom = std::max(scaled_source_rect.bottom, 0);
// Transition the EFB render target to a shader resource.
VkRect2D src_region = { { 0, 0 },
{ static_cast<u32>(scaled_source_rect.GetWidth()),
static_cast<u32>(scaled_source_rect.GetHeight()) } };
Texture2D* efb_color_texture =
FramebufferManager::GetInstance()->ResolveEFBColorTexture(src_region);
g_ActiveConfig.iMultisamples > 1 ?
FramebufferManager::GetInstance()->GetResolvedEFBColorTexture() :
FramebufferManager::GetInstance()->GetEFBColorTexture();
efb_color_texture->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(),
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
// Copy EFB -> backbuffer
BlitScreen(render_pass, target_rect, scaled_source_rect, efb_color_texture, true);
BlitScreen(render_pass, target_rect, scaled_efb_rect, efb_color_texture, true);
// Restore the EFB color texture to color attachment ready for rendering the next frame.
if (efb_color_texture == FramebufferManager::GetInstance()->GetEFBColorTexture())
@@ -667,7 +696,7 @@ void Renderer::DrawRealXFB(VkRenderPass render_pass, const TargetRectangle& targ
}
}
void Renderer::DrawScreen(const EFBRectangle& source_rect, u32 xfb_addr,
void Renderer::DrawScreen(const TargetRectangle& scaled_efb_rect, u32 xfb_addr,
const XFBSourceBase* const* xfb_sources, u32 xfb_count, u32 fb_width,
u32 fb_stride, u32 fb_height)
{
@@ -710,8 +739,8 @@ void Renderer::DrawScreen(const EFBRectangle& source_rect, u32 xfb_addr,
VK_SUBPASS_CONTENTS_INLINE);
// Draw guest buffers (EFB or XFB)
DrawFrame(m_swap_chain->GetRenderPass(), GetTargetRectangle(), source_rect, xfb_addr, xfb_sources,
xfb_count, fb_width, fb_stride, fb_height);
DrawFrame(m_swap_chain->GetRenderPass(), GetTargetRectangle(), scaled_efb_rect, xfb_addr,
xfb_sources, xfb_count, fb_width, fb_stride, fb_height);
// Draw OSD
Util::SetViewportAndScissor(g_command_buffer_mgr->GetCurrentCommandBuffer(), 0, 0,
@@ -729,7 +758,7 @@ void Renderer::DrawScreen(const EFBRectangle& source_rect, u32 xfb_addr,
VK_IMAGE_LAYOUT_PRESENT_SRC_KHR);
}
bool Renderer::DrawFrameDump(const EFBRectangle& source_rect, u32 xfb_addr,
bool Renderer::DrawFrameDump(const TargetRectangle& scaled_efb_rect, u32 xfb_addr,
const XFBSourceBase* const* xfb_sources, u32 xfb_count, u32 fb_width,
u32 fb_stride, u32 fb_height, u64 ticks)
{
@@ -739,6 +768,10 @@ bool Renderer::DrawFrameDump(const EFBRectangle& source_rect, u32 xfb_addr,
if (!ResizeFrameDumpBuffer(width, height))
return false;
// If there was a previous frame dumped, we'll still be in TRANSFER_SRC layout.
m_frame_dump_render_texture->TransitionToLayout(g_command_buffer_mgr->GetCurrentCommandBuffer(),
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
VkClearValue clear_value = { { { 0.0f, 0.0f, 0.0f, 1.0f } } };
VkClearRect clear_rect = { { { 0, 0 },{ width, height } }, 0, 1 };
VkClearAttachment clear_attachment = { VK_IMAGE_ASPECT_COLOR_BIT, 0, clear_value };
@@ -755,7 +788,7 @@ bool Renderer::DrawFrameDump(const EFBRectangle& source_rect, u32 xfb_addr,
vkCmdClearAttachments(g_command_buffer_mgr->GetCurrentCommandBuffer(), 1, &clear_attachment, 1,
&clear_rect);
DrawFrame(FramebufferManager::GetInstance()->GetColorCopyForReadbackRenderPass(), target_rect,
source_rect, xfb_addr, xfb_sources, xfb_count, fb_width, fb_stride, fb_height);
scaled_efb_rect, xfb_addr, xfb_sources, xfb_count, fb_width, fb_stride, fb_height);
vkCmdEndRenderPass(g_command_buffer_mgr->GetCurrentCommandBuffer());
// Prepare the readback texture for copying.
@@ -910,7 +943,7 @@ void Renderer::BlitScreen(VkRenderPass render_pass, const TargetRectangle& dst_r
{
TargetRectangle left_rect;
TargetRectangle right_rect;
ConvertStereoRectangle(dst_rect, left_rect, right_rect);
std::tie(left_rect, right_rect) = ConvertStereoRectangle(dst_rect);
draw.DrawQuad(left_rect.left, left_rect.top, left_rect.GetWidth(), left_rect.GetHeight(),
src_rect.left, src_rect.top, 0, src_rect.GetWidth(), src_rect.GetHeight(),
@@ -936,6 +969,10 @@ bool Renderer::ResizeFrameDumpBuffer(u32 new_width, u32 new_height)
return true;
}
// Ensure all previous frames have been dumped, since we are destroying a framebuffer
// that may still be in use.
FlushFrameDump();
if (m_frame_dump_framebuffer != VK_NULL_HANDLE)
{
vkDestroyFramebuffer(g_vulkan_context->GetDevice(), m_frame_dump_framebuffer, nullptr);
@@ -1023,22 +1060,22 @@ void Renderer::CheckForTargetResize(u32 fb_width, u32 fb_stride, u32 fb_height)
void Renderer::CheckForSurfaceChange()
{
if (!s_surface_needs_change.IsSet())
if (!m_surface_needs_change.IsSet())
return;
u32 old_width = m_swap_chain ? m_swap_chain->GetWidth() : 0;
u32 old_height = m_swap_chain ? m_swap_chain->GetHeight() : 0;
// Fast path, if the surface handle is the same, the window has just been resized.
if (m_swap_chain && s_new_surface_handle == m_swap_chain->GetNativeHandle())
if (m_swap_chain && m_new_surface_handle == m_swap_chain->GetNativeHandle())
{
INFO_LOG(VIDEO, "Detected window resize.");
ResizeSwapChain();
// Notify the main thread we are done.
s_surface_needs_change.Clear();
s_new_surface_handle = nullptr;
s_surface_changed.Set();
m_surface_needs_change.Clear();
m_new_surface_handle = nullptr;
m_surface_changed.Set();
}
else
{
@@ -1048,7 +1085,7 @@ void Renderer::CheckForSurfaceChange()
// Did we previously have a swap chain?
if (m_swap_chain)
{
if (!s_new_surface_handle)
if (!m_new_surface_handle)
{
// If there is no surface now, destroy the swap chain.
m_swap_chain.reset();
@@ -1056,7 +1093,7 @@ void Renderer::CheckForSurfaceChange()
else
{
// Recreate the surface. If this fails we're in trouble.
if (!m_swap_chain->RecreateSurface(s_new_surface_handle))
if (!m_swap_chain->RecreateSurface(m_new_surface_handle))
PanicAlert("Failed to recreate Vulkan surface. Cannot continue.");
}
}
@@ -1064,10 +1101,10 @@ void Renderer::CheckForSurfaceChange()
{
// Previously had no swap chain. So create one.
VkSurfaceKHR surface = SwapChain::CreateVulkanSurface(g_vulkan_context->GetVulkanInstance(),
s_new_surface_handle);
m_new_surface_handle);
if (surface != VK_NULL_HANDLE)
{
m_swap_chain = SwapChain::Create(s_new_surface_handle, surface, g_ActiveConfig.IsVSync());
m_swap_chain = SwapChain::Create(m_new_surface_handle, surface, g_ActiveConfig.IsVSync());
if (!m_swap_chain)
PanicAlert("Failed to create swap chain.");
}
@@ -1078,9 +1115,9 @@ void Renderer::CheckForSurfaceChange()
}
// Notify calling thread.
s_surface_needs_change.Clear();
s_new_surface_handle = nullptr;
s_surface_changed.Set();
m_surface_needs_change.Clear();
m_new_surface_handle = nullptr;
m_surface_changed.Set();
}
if (m_swap_chain)
@@ -1114,7 +1151,7 @@ void Renderer::CheckForConfigChanges()
bool anisotropy_changed = old_anisotropy != g_ActiveConfig.iMaxAnisotropy;
bool force_texture_filtering_changed = old_force_filtering != g_ActiveConfig.bForceFiltering;
bool stereo_changed = old_stereo_mode != g_ActiveConfig.iStereoMode;
bool efb_scale_changed = s_last_efb_scale != g_ActiveConfig.iEFBScale;
bool efb_scale_changed = m_last_efb_scale != g_ActiveConfig.iEFBScale;
bool aspect_changed = old_aspect_ratio != g_ActiveConfig.iAspectRatio;
bool use_xfb_changed = old_use_xfb != g_ActiveConfig.bUseXFB;
bool use_realxfb_changed = old_use_realxfb != g_ActiveConfig.bUseRealXFB;
@@ -1125,7 +1162,7 @@ void Renderer::CheckForConfigChanges()
// Handle settings that can cause the target rectangle to change.
if (efb_scale_changed || aspect_changed || use_xfb_changed || use_realxfb_changed)
{
s_last_efb_scale = g_ActiveConfig.iEFBScale;
m_last_efb_scale = g_ActiveConfig.iEFBScale;
if (CalculateTargetSize())
ResizeEFBTextures();
}
@@ -1146,7 +1183,7 @@ void Renderer::CheckForConfigChanges()
{
g_command_buffer_mgr->WaitForGPUIdle();
RecompileShaders();
FramebufferManager::GetInstance()->RecompileShaders();
FramebufferManager::GetInstance()->RecompileShaders();
g_object_cache->RecompileSharedShaders();
StateTracker::GetInstance()->LoadPipelineUIDCache();
}
@@ -1165,8 +1202,8 @@ void Renderer::CheckForConfigChanges()
void Renderer::OnSwapChainResized()
{
s_backbuffer_width = m_swap_chain->GetWidth();
s_backbuffer_height = m_swap_chain->GetHeight();
m_backbuffer_width = m_swap_chain->GetWidth();
m_backbuffer_height = m_swap_chain->GetHeight();
UpdateDrawRectangle();
if (CalculateTargetSize())
{
@@ -1617,16 +1654,14 @@ void Renderer::ResetSamplerStates()
g_object_cache->ClearSamplerCache();
}
void Renderer::SetDitherMode()
{
}
void Renderer::SetInterlacingMode()
{
}
void Renderer::SetScissorRect(const TargetRectangle& target_rc)
void Renderer::SetScissorRect(const EFBRectangle& rc)
{
TargetRectangle target_rc = ConvertEFBRectangle(rc);
VkRect2D scissor = {
{ target_rc.left, target_rc.top },
{ static_cast<uint32_t>(target_rc.GetWidth()), static_cast<uint32_t>(target_rc.GetHeight()) } };
@@ -1639,10 +1674,10 @@ void Renderer::SetViewport()
int scissor_x_offset = bpmem.scissorOffset.x * 2;
int scissor_y_offset = bpmem.scissorOffset.y * 2;
float x = Renderer::EFBToScaledXf(xfmem.viewport.xOrig - xfmem.viewport.wd - scissor_x_offset);
float y = Renderer::EFBToScaledYf(xfmem.viewport.yOrig + xfmem.viewport.ht - scissor_y_offset);
float width = Renderer::EFBToScaledXf(2.0f * xfmem.viewport.wd);
float height = Renderer::EFBToScaledYf(-2.0f * xfmem.viewport.ht);
float x = g_renderer->EFBToScaledXf(xfmem.viewport.xOrig - xfmem.viewport.wd - scissor_x_offset);
float y = g_renderer->EFBToScaledYf(xfmem.viewport.yOrig + xfmem.viewport.ht - scissor_y_offset);
float width = g_renderer->EFBToScaledXf(2.0f * xfmem.viewport.wd);
float height = g_renderer->EFBToScaledYf(-2.0f * xfmem.viewport.ht);
float range = MathUtil::Clamp<float>(xfmem.viewport.zRange, -16777215.0f, 16777215.0f);
float min_depth =
@@ -1679,9 +1714,9 @@ void Renderer::SetViewport()
void Renderer::ChangeSurface(void* new_surface_handle)
{
// Called by the main thread when the window is resized.
s_new_surface_handle = new_surface_handle;
s_surface_needs_change.Set();
s_surface_changed.Set();
m_new_surface_handle = new_surface_handle;
m_surface_needs_change.Set();
m_surface_changed.Set();
}
void Renderer::RecompileShaders()

View File

@@ -29,7 +29,7 @@ class Renderer : public ::Renderer
public:
Renderer(std::unique_ptr<SwapChain> swap_chain);
~Renderer();
void Init() override;
static Renderer* GetInstance();
SwapChain* GetSwapChain() const { return m_swap_chain.get(); }
@@ -58,11 +58,10 @@ public:
void SetColorMask() override;
void SetBlendMode(bool force_update) override;
void SetScissorRect(const TargetRectangle& rc) override;
void SetScissorRect(const EFBRectangle& rc) override;
void SetGenerationMode() override;
void SetDepthMode() override;
void SetLogicOpMode() override;
void SetDitherMode() override;
void SetSamplerState(int stage, int texindex, bool custom_tex) override;
void SetInterlacingMode() override;
void SetViewport() override;
@@ -90,13 +89,15 @@ private:
bool CompileShaders();
void DestroyShaders();
void ResolveEFBForSwap(const TargetRectangle& scaled_rect);
// Draw either the EFB, or specified XFB sources to the currently-bound framebuffer.
void DrawFrame(VkRenderPass render_pass, const TargetRectangle& target_rect,
const EFBRectangle& source_rect, u32 xfb_addr,
const TargetRectangle& scaled_efb_rect, u32 xfb_addr,
const XFBSourceBase* const* xfb_sources, u32 xfb_count, u32 fb_width,
u32 fb_stride, u32 fb_height);
void DrawEFB(VkRenderPass render_pass, const TargetRectangle& target_rect,
const EFBRectangle& source_rect);
const TargetRectangle& scaled_efb_rect);
void DrawVirtualXFB(VkRenderPass render_pass, const TargetRectangle& target_rect, u32 xfb_addr,
const XFBSourceBase* const* xfb_sources, u32 xfb_count, u32 fb_width,
u32 fb_stride, u32 fb_height);
@@ -105,11 +106,11 @@ private:
u32 fb_stride, u32 fb_height);
// Draw the frame, as well as the OSD to the swap chain.
void DrawScreen(const EFBRectangle& rc, u32 xfb_addr, const XFBSourceBase* const* xfb_sources,
void DrawScreen(const TargetRectangle& scaled_efb_rect, u32 xfb_addr, const XFBSourceBase* const* xfb_sources,
u32 xfb_count, u32 fb_width, u32 fb_stride, u32 fb_height);
// Draw the frame only to the screenshot buffer.
bool DrawFrameDump(const EFBRectangle& rc, u32 xfb_addr, const XFBSourceBase* const* xfb_sources,
bool DrawFrameDump(const TargetRectangle& scaled_efb_rect, u32 xfb_addr, const XFBSourceBase* const* xfb_sources,
u32 xfb_count, u32 fb_width, u32 fb_stride, u32 fb_height, u64 ticks);
// Sets up renderer state to permit framedumping.

View File

@@ -35,7 +35,7 @@ static const TBuiltInResource* GetCompilerResourceLimits();
// Compile a shader to SPIR-V via glslang
static bool CompileShaderToSPV(SPIRVCodeVector* out_code, EShLanguage stage,
const char* stage_filename, const char* source_code,
size_t source_code_length, bool prepend_header);
size_t source_code_length, const char* header, size_t header_length);
// Regarding the UBO bind points, we subtract one from the binding index because
// the OpenGL backend requires UBO #0 for non-block uniforms (at least on NV).
@@ -66,27 +66,62 @@ static const char SHADER_HEADER[] = R"(
#define int2 ivec2
#define int3 ivec3
#define int4 ivec4
#define float1x1 mat1
#define float2x2 mat2
#define float3x3 mat3
#define float4x4 mat4
#define float4x3 mat4x3
#define float3x4 mat3x4
#define float1x1 mat1
#define float2x2 mat2
#define float3x3 mat3
#define float4x4 mat4
#define float4x3 mat4x3
#define float3x4 mat3x4
#define frac fract
#define lerp mix
#define saturate(x) clamp(x, 0.0, 1.0)
#define mul(x, y) (y * x)
#define ddx dFdx
#define ddy dFdy
#define rsqrt inversesqrt
#define saturate(x) clamp(x, 0.0, 1.0)
#define mul(x, y) (y * x)
#define ddx dFdx
#define ddy dFdy
#define rsqrt inversesqrt
// These were changed in Vulkan
#define gl_VertexID gl_VertexIndex
#define gl_InstanceID gl_InstanceIndex
)";
static const char COMPUTE_SHADER_HEADER[] = R"(
// Target GLSL 4.5.
#version 450 core
// All resources are packed into one descriptor set for compute.
#define UBO_BINDING(packing, x) layout(packing, set = 0, binding = (0 + x))
#define SAMPLER_BINDING(x) layout(set = 0, binding = (1 + x))
#define TEXEL_BUFFER_BINDING(x) layout(set = 0, binding = (5 + x))
#define IMAGE_BINDING(format, x) layout(format, set = 0, binding = (7 + x))
// hlsl to glsl function translation
#define float2 vec2
#define float3 vec3
#define float4 vec4
#define uint2 uvec2
#define uint3 uvec3
#define uint4 uvec4
#define int2 ivec2
#define int3 ivec3
#define int4 ivec4
#define float1x1 mat1
#define float2x2 mat2
#define float3x3 mat3
#define float4x4 mat4
#define float4x3 mat4x3
#define float3x4 mat3x4
#define frac fract
#define lerp mix
#define saturate(x) clamp(x, 0.0, 1.0)
#define mul(x, y) (y * x)
#define ddx dFdx
#define ddy dFdy
#define rsqrt inversesqrt
)";
bool CompileShaderToSPV(SPIRVCodeVector* out_code, EShLanguage stage, const char* stage_filename,
const char* source_code, size_t source_code_length, bool prepend_header)
const char* source_code, size_t source_code_length, const char* header,
size_t header_length)
{
if (!InitializeGlslang())
return false;
@@ -102,10 +137,10 @@ bool CompileShaderToSPV(SPIRVCodeVector* out_code, EShLanguage stage, const char
std::string full_source_code;
const char* pass_source_code = source_code;
int pass_source_code_length = static_cast<int>(source_code_length);
if (prepend_header)
if (header_length > 0)
{
full_source_code.reserve(sizeof(SHADER_HEADER) + source_code_length);
full_source_code.append(SHADER_HEADER, sizeof(SHADER_HEADER) - 1);
full_source_code.reserve(header_length + source_code_length);
full_source_code.append(header, header_length);
full_source_code.append(source_code, source_code_length);
pass_source_code = full_source_code.c_str();
pass_source_code_length = static_cast<int>(full_source_code.length());
@@ -329,21 +364,28 @@ bool CompileVertexShader(SPIRVCodeVector* out_code, const char* source_code,
size_t source_code_length, bool prepend_header)
{
return CompileShaderToSPV(out_code, EShLangVertex, "vs", source_code, source_code_length,
prepend_header);
SHADER_HEADER, sizeof(SHADER_HEADER) - 1);
}
bool CompileGeometryShader(SPIRVCodeVector* out_code, const char* source_code,
size_t source_code_length, bool prepend_header)
{
return CompileShaderToSPV(out_code, EShLangGeometry, "gs", source_code, source_code_length,
prepend_header);
SHADER_HEADER, sizeof(SHADER_HEADER) - 1);
}
bool CompileFragmentShader(SPIRVCodeVector* out_code, const char* source_code,
size_t source_code_length, bool prepend_header)
{
return CompileShaderToSPV(out_code, EShLangFragment, "ps", source_code, source_code_length,
prepend_header);
SHADER_HEADER, sizeof(SHADER_HEADER) - 1);
}
bool CompileComputeShader(SPIRVCodeVector* out_code, const char* source_code,
size_t source_code_length, bool prepend_header)
{
return CompileShaderToSPV(out_code, EShLangCompute, "cs", source_code, source_code_length,
COMPUTE_SHADER_HEADER, sizeof(COMPUTE_SHADER_HEADER) - 1);
}
} // namespace ShaderCompiler

View File

@@ -29,5 +29,9 @@ bool CompileGeometryShader(SPIRVCodeVector* out_code, const char* source_code,
bool CompileFragmentShader(SPIRVCodeVector* out_code, const char* source_code,
size_t source_code_length, bool prepend_header = true);
// Compile a compute shader to SPIR-V.
bool CompileComputeShader(SPIRVCodeVector* out_code, const char* source_code,
size_t source_code_length, bool prepend_header = true);
} // namespace ShaderCompiler
} // namespace Vulkan

View File

@@ -127,7 +127,7 @@ void StagingBuffer::InvalidateCPUCache(VkDeviceSize offset, VkDeviceSize size)
void StagingBuffer::Read(VkDeviceSize offset, void* data, size_t size, bool invalidate_caches)
{
_assert_((offset + size) <= m_size);
_assert_(offset >= m_map_offset && size < (m_map_size + (offset - m_map_offset)));
_assert_(offset >= m_map_offset && size <= (m_map_size + (offset - m_map_offset)));
if (invalidate_caches)
InvalidateCPUCache(offset, size);
@@ -138,7 +138,7 @@ void StagingBuffer::Write(VkDeviceSize offset, const void* data, size_t size,
bool invalidate_caches)
{
_assert_((offset + size) <= m_size);
_assert_(offset >= m_map_offset && size < (m_map_size + (offset - m_map_offset)));
_assert_(offset >= m_map_offset && size <= (m_map_size + (offset - m_map_offset)));
memcpy(m_map_pointer + (offset - m_map_offset), data, size);
if (invalidate_caches)

View File

@@ -4,6 +4,7 @@
#include <algorithm>
#include "Common/Assert.h"
#include "VideoBackends/Vulkan/CommandBufferManager.h"
#include "VideoBackends/Vulkan/Texture2D.h"
#include "VideoBackends/Vulkan/VulkanContext.h"
@@ -12,16 +13,30 @@ namespace Vulkan
{
Texture2D::Texture2D(u32 width, u32 height, u32 levels, u32 layers, VkFormat format,
VkSampleCountFlagBits samples, VkImageViewType view_type, VkImage image,
VkDeviceMemory device_memory, VkImageView view)
VkDeviceMemory device_memory, VkImageView view, VkFramebuffer framebuffer)
: m_width(width), m_height(height), m_levels(levels), m_layers(layers), m_format(format),
m_samples(samples), m_view_type(view_type), m_image(image), m_device_memory(device_memory),
m_view(view)
m_view(view), m_framebuffer(framebuffer)
{
if (framebuffer != VK_NULL_HANDLE)
{
// Clear render targets before use to prevent reading uninitialized memory.
VkClearColorValue clear_value = { { 0.0f, 0.0f, 0.0f, 1.0f } };
VkImageSubresourceRange clear_range = { VK_IMAGE_ASPECT_COLOR_BIT, 0, levels, 0,
layers };
TransitionToLayout(g_command_buffer_mgr->GetCurrentInitCommandBuffer(),
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
vkCmdClearColorImage(g_command_buffer_mgr->GetCurrentInitCommandBuffer(), image,
m_layout, &clear_value, 1, &clear_range);
}
}
Texture2D::~Texture2D()
{
g_command_buffer_mgr->DeferImageViewDestruction(m_view);
if (m_framebuffer != VK_NULL_HANDLE)
g_command_buffer_mgr->DeferFramebufferDestruction(m_framebuffer);
// If we don't have device memory allocated, the image is not owned by us (e.g. swapchain)
if (m_device_memory != VK_NULL_HANDLE)
@@ -34,7 +49,7 @@ Texture2D::~Texture2D()
std::unique_ptr<Texture2D> Texture2D::Create(u32 width, u32 height, u32 levels, u32 layers,
VkFormat format, VkSampleCountFlagBits samples,
VkImageViewType view_type, VkImageTiling tiling,
VkImageUsageFlags usage)
VkImageUsageFlags usage, VkRenderPass renderpass)
{
VkImageCreateInfo image_info = { VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
nullptr,
@@ -109,9 +124,32 @@ std::unique_ptr<Texture2D> Texture2D::Create(u32 width, u32 height, u32 levels,
vkFreeMemory(g_vulkan_context->GetDevice(), device_memory, nullptr);
return nullptr;
}
VkFramebuffer framebuffer = VK_NULL_HANDLE;
if (usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT && renderpass != VK_NULL_HANDLE)
{
VkImageView framebuffer_attachments[] = { view };
VkFramebufferCreateInfo framebuffer_info = {
VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
nullptr,
0,
renderpass,
static_cast<u32>(ArraySize(framebuffer_attachments)),
framebuffer_attachments,
width,
height,
layers };
VkResult res = vkCreateFramebuffer(g_vulkan_context->GetDevice(), &framebuffer_info, nullptr,
&framebuffer);
if (res != VK_SUCCESS)
{
LOG_VULKAN_ERROR(res, "vkCreateFramebuffer failed: ");
return nullptr;
}
}
return std::make_unique<Texture2D>(width, height, levels, layers, format, samples, view_type,
image, device_memory, view);
image, device_memory, view, framebuffer);
}
std::unique_ptr<Texture2D> Texture2D::CreateFromExistingImage(u32 width, u32 height, u32 levels,
@@ -145,7 +183,7 @@ std::unique_ptr<Texture2D> Texture2D::CreateFromExistingImage(u32 width, u32 hei
}
return std::make_unique<Texture2D>(width, height, levels, layers, format, samples, view_type,
existing_image, memory, view);
existing_image, memory, view, nullptr);
}
void Texture2D::OverrideImageLayout(VkImageLayout new_layout)
@@ -273,10 +311,132 @@ void Texture2D::TransitionToLayout(VkCommandBuffer command_buffer, VkImageLayout
break;
}
// If we were using a compute layout, the stages need to reflect that
switch (m_compute_layout)
{
case ComputeImageLayout::Undefined:
break;
case ComputeImageLayout::ReadOnly:
barrier.srcAccessMask = VK_ACCESS_SHADER_READ_BIT;
srcStageMask = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
break;
case ComputeImageLayout::WriteOnly:
barrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT;
srcStageMask = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
break;
case ComputeImageLayout::ReadWrite:
barrier.srcAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
srcStageMask = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
break;
}
m_compute_layout = ComputeImageLayout::Undefined;
vkCmdPipelineBarrier(command_buffer, srcStageMask, dstStageMask, 0, 0, nullptr, 0, nullptr, 1,
&barrier);
m_layout = new_layout;
}
void Texture2D::TransitionToLayout(VkCommandBuffer command_buffer, ComputeImageLayout new_layout)
{
_assert_(new_layout != ComputeImageLayout::Undefined);
if (m_compute_layout == new_layout)
return;
VkImageMemoryBarrier barrier = {
VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType
nullptr, // const void* pNext
0, // VkAccessFlags srcAccessMask
0, // VkAccessFlags dstAccessMask
m_layout, // VkImageLayout oldLayout
VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout newLayout
VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex
VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex
m_image, // VkImage image
{ static_cast<VkImageAspectFlags>(Util::IsDepthFormat(m_format) ? VK_IMAGE_ASPECT_DEPTH_BIT :
VK_IMAGE_ASPECT_COLOR_BIT),
0, m_levels, 0, m_layers } // VkImageSubresourceRange subresourceRange
};
VkPipelineStageFlags srcStageMask, dstStageMask;
switch (m_layout)
{
case VK_IMAGE_LAYOUT_UNDEFINED:
// Layout undefined therefore contents undefined, and we don't care what happens to it.
barrier.srcAccessMask = 0;
srcStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
break;
case VK_IMAGE_LAYOUT_PREINITIALIZED:
// Image has been pre-initialized by the host, so ensure all writes have completed.
barrier.srcAccessMask = VK_ACCESS_HOST_WRITE_BIT;
srcStageMask = VK_PIPELINE_STAGE_HOST_BIT;
break;
case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL:
// Image was being used as a color attachment, so ensure all writes have completed.
barrier.srcAccessMask =
VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
break;
case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL:
// Image was being used as a depthstencil attachment, so ensure all writes have completed.
barrier.srcAccessMask =
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
break;
case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL:
// Image was being used as a shader resource, make sure all reads have finished.
barrier.srcAccessMask = VK_ACCESS_SHADER_READ_BIT;
srcStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
break;
case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL:
// Image was being used as a copy source, ensure all reads have finished.
barrier.srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
srcStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT;
break;
case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL:
// Image was being used as a copy destination, ensure all writes have finished.
barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
srcStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT;
break;
default:
srcStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
break;
}
switch (new_layout)
{
case ComputeImageLayout::ReadOnly:
barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
barrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
dstStageMask = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
break;
case ComputeImageLayout::WriteOnly:
barrier.dstAccessMask = VK_ACCESS_SHADER_WRITE_BIT;
barrier.newLayout = VK_IMAGE_LAYOUT_GENERAL;
dstStageMask = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
break;
case ComputeImageLayout::ReadWrite:
barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
barrier.newLayout = VK_IMAGE_LAYOUT_GENERAL;
dstStageMask = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
break;
default:
dstStageMask = 0;
break;
}
m_layout = barrier.newLayout;
m_compute_layout = new_layout;
vkCmdPipelineBarrier(command_buffer, srcStageMask, dstStageMask, 0, 0, nullptr, 0, nullptr, 1,
&barrier);
}
} // namespace Vulkan

Some files were not shown because too many files have changed in this diff Show More