mirror of
https://github.com/project-slippi/Ishiiruka.git
synced 2025-10-06 00:12:42 +02:00
merge latest master changes
This commit is contained in:
19
Externals/xbrz/config.h
vendored
19
Externals/xbrz/config.h
vendored
@@ -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
|
||||
};
|
||||
}
|
||||
|
||||
|
961
Externals/xbrz/xbrz.cpp
vendored
961
Externals/xbrz/xbrz.cpp
vendored
File diff suppressed because it is too large
Load Diff
54
Externals/xbrz/xbrz.h
vendored
54
Externals/xbrz/xbrz.h
vendored
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -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" />
|
||||
|
@@ -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" />
|
||||
|
53
Source/Core/Common/GL/GLExtensions/ARB_compute_shader.h
Normal file
53
Source/Core/Common/GL/GLExtensions/ARB_compute_shader.h
Normal 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
|
100
Source/Core/Common/GL/GLExtensions/ARB_shader_image_load_store.h
Normal file
100
Source/Core/Common/GL/GLExtensions/ARB_shader_image_load_store.h
Normal 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
|
41
Source/Core/Common/GL/GLExtensions/ARB_texture_storage.h
Normal file
41
Source/Core/Common/GL/GLExtensions/ARB_texture_storage.h
Normal 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
|
@@ -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
|
@@ -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;
|
||||
|
@@ -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"
|
||||
|
41
Source/Core/Common/GL/GLExtensions/NV_depth_buffer_float.h
Normal file
41
Source/Core/Common/GL/GLExtensions/NV_depth_buffer_float.h
Normal 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
|
@@ -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
|
||||
|
@@ -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
|
||||
|
70
Source/Core/Common/GL/GLInterface/BGL.cpp
Normal file
70
Source/Core/Common/GL/GLInterface/BGL.cpp
Normal 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());
|
||||
}
|
27
Source/Core/Common/GL/GLInterface/BGL.h
Normal file
27
Source/Core/Common/GL/GLInterface/BGL.h
Normal 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;
|
||||
};
|
@@ -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;
|
||||
}
|
||||
}
|
||||
|
30
Source/Core/Common/GL/GLInterface/EGLHaiku.cpp
Normal file
30
Source/Core/Common/GL/GLInterface/EGLHaiku.cpp
Normal 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()
|
||||
{
|
||||
}
|
16
Source/Core/Common/GL/GLInterface/EGLHaiku.h
Normal file
16
Source/Core/Common/GL/GLInterface/EGLHaiku.h
Normal 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;
|
||||
};
|
@@ -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
|
||||
|
@@ -4,6 +4,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <windows.h>
|
||||
#include <string>
|
||||
#include "Common/GL/GLInterfaceBase.h"
|
||||
|
||||
|
@@ -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;
|
||||
|
@@ -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);
|
||||
|
@@ -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();
|
||||
}
|
||||
|
@@ -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;
|
||||
|
@@ -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">
|
||||
|
@@ -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
|
||||
|
@@ -6,6 +6,7 @@
|
||||
|
||||
#include <atomic>
|
||||
#include <d3d12.h>
|
||||
#include <dxgi.h>
|
||||
#include <thread>
|
||||
|
||||
namespace DX12
|
||||
|
@@ -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);
|
||||
|
@@ -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(),
|
||||
|
@@ -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();
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -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();
|
||||
|
||||
|
@@ -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);
|
||||
|
@@ -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);
|
||||
|
||||
|
@@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
|
@@ -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();
|
||||
|
@@ -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
|
||||
{
|
||||
|
@@ -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;
|
||||
|
||||
};
|
||||
}
|
||||
|
@@ -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()));
|
||||
}
|
||||
|
@@ -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>();
|
||||
|
@@ -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);
|
||||
|
@@ -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:
|
||||
|
@@ -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, ¶ms, 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, ¶ms, 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;
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -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;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
@@ -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,
|
||||
|
@@ -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();
|
||||
|
@@ -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);
|
||||
|
@@ -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, ¶ms, 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;
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -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;
|
||||
};
|
||||
|
||||
}
|
@@ -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);
|
||||
|
||||
|
@@ -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;
|
||||
};
|
||||
|
||||
}
|
@@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -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;
|
||||
|
@@ -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;
|
||||
|
||||
|
@@ -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);
|
||||
}
|
||||
|
||||
|
@@ -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>();
|
||||
|
@@ -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));
|
||||
|
@@ -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()
|
||||
|
@@ -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
|
||||
|
@@ -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
|
@@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -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
|
||||
|
@@ -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,
|
||||
|
@@ -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);
|
||||
|
||||
|
||||
}
|
||||
|
@@ -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());
|
||||
}
|
||||
|
||||
|
@@ -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();
|
||||
}
|
||||
|
||||
|
@@ -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);
|
||||
|
105
Source/Core/VideoBackends/OGL/GPUTimer.h
Normal file
105
Source/Core/VideoBackends/OGL/GPUTimer.h
Normal 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
|
@@ -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" />
|
||||
|
@@ -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" />
|
||||
|
@@ -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;" : ""
|
||||
);
|
||||
}
|
||||
|
||||
|
@@ -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();
|
||||
|
||||
|
@@ -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];
|
||||
|
@@ -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);
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -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 = {};
|
||||
|
@@ -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();
|
||||
|
@@ -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);
|
||||
|
||||
}
|
||||
|
||||
|
@@ -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);
|
||||
|
||||
|
@@ -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;
|
||||
};
|
||||
}
|
||||
|
@@ -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();
|
||||
|
@@ -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();
|
||||
|
@@ -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;
|
||||
|
@@ -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>();
|
||||
|
||||
|
@@ -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)
|
||||
|
||||
|
@@ -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,
|
||||
|
@@ -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;
|
||||
|
@@ -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);
|
||||
|
@@ -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);
|
||||
|
@@ -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++)
|
||||
{
|
||||
|
@@ -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;
|
||||
|
||||
|
@@ -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;
|
||||
|
||||
|
@@ -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,
|
||||
|
@@ -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()
|
||||
|
@@ -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.
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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)
|
||||
|
@@ -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
Reference in New Issue
Block a user